// Copyright 2013 the V8 project authors. All rights reserved. // Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. description("KDE JS Test"); // 15.4 Array Objects // (c) 2001 Harri Porten shouldBe("Array().length", "0"); shouldBe("(new Array()).length", "0"); shouldBe("(new Array(3)).length", "3"); shouldBe("(new Array(11, 22)).length", "2"); shouldBe("(new Array(11, 22))[0]", "11"); shouldBe("Array(11, 22)[1]", "22"); shouldBeUndefined("(new Array(11, 22))[3]"); shouldBe("String(new Array(11, 22))", "'11,22'"); shouldBe("var a = []; a[0] = 33; a[0]", "33"); shouldBe("var a = []; a[0] = 33; a.length", "1"); shouldBe("var a = [11, 22]; a.length = 1; String(a);", "'11'"); shouldBe("var a = [11, 22]; a.length = 1; a.length;", "1"); // range checks var caught = false; var ename = ""; try { [].length = -1; } catch (e) { // expect Range Error caught = true; ename = e.name; } shouldBeTrue("caught;"); shouldBe("ename", "'RangeError'"); caught = false; ename = ""; try { new Array(Infinity); } catch (e) { // expect Range Error caught = true; ename = e.name; } shouldBeTrue("caught;"); shouldBe("ename", "'RangeError'"); shouldBeUndefined("var a = [11, 22]; a.length = 1; a[1];"); shouldBe("Array().toString()", "''"); shouldBe("Array(3).toString()", "',,'"); shouldBe("Array(11, 22).toString()", "'11,22'"); shouldBe("String(Array(11, 22).concat(33))", "'11,22,33'"); shouldBe("String(Array(2).concat(33, 44))", "',,33,44'"); shouldBe("String(Array(2).concat(Array(2)))", "',,,'"); shouldBe("String(Array(11,22).concat(Array(33,44)))", "'11,22,33,44'"); shouldBe("String(Array(1,2).concat(3,Array(4,5)))", "'1,2,3,4,5'"); shouldBe("var a = new Array(1,2,3); delete a[1]; String(a.concat(4))", "'1,,3,4'"); shouldBe("[1,2,3,4].slice(1, 3).toString()", "'2,3'"); shouldBe("[1,2,3,4].slice(-3, -1).toString()", "'2,3'"); shouldBe("[1,2].slice(-9, 0).length", "0"); shouldBe("[1,2].slice(1).toString()", "'2'"); shouldBe("[1,2].slice().toString()", "'1,2'"); // 2nd set. shouldBe("(new Array('a')).length", "1"); shouldBe("(new Array('a'))[0]", "'a'"); shouldBeUndefined("(new Array('a'))[1]"); shouldBe("Array('a').length", "1"); shouldBe("Array('a')[0]", "'a'"); shouldBe("String(Array())", "''"); shouldBe("String(Array('a','b'))", "'a,b'"); shouldBe("[].length", "0"); shouldBe("['a'].length", "1"); shouldBe("['a'][0]", "'a'"); shouldBe("['a',,'c'][2]", "'c'"); shouldBe("['a',undefined,'c'][1]", "undefined"); shouldBe("['a',,'c'][1]", "undefined"); shouldBe("1 in ['a',,'c']", "false"); shouldBe("1 in ['a',undefined,'c']", "true"); var arrayWithDeletion = ['a','b','c']; delete arrayWithDeletion[1]; shouldBe("1 in arrayWithDeletion", "false"); function forInSum(_a) { var s = ''; for (i in _a) s += _a[i]; return s; } shouldBe("forInSum([])", "''"); shouldBe("forInSum(Array())", "''"); shouldBe("forInSum(Array('a'))", "'a'"); shouldBe("forInSum([,undefined,'x','aa'])", "'undefinedxaa'"); var a0 = []; shouldBe("forInSum(a0)", "''"); var a1 = [ 'a' ]; shouldBe("forInSum(a1)", "'a'"); shouldBe("String([].sort())", "''") shouldBe("String([3,1,'2'].sort())", "'1,2,3'"); shouldBe("String([,'x','aa'].sort())", "'aa,x,'"); shouldBe("String([,undefined,'x','aa'].sort())", "'aa,x,,'"); shouldBe("2 in [,undefined,'x','aa'].sort()", "true"); shouldBe("3 in [,undefined,'x','aa'].sort()", "false"); // sort by length function comp(a, b) { var la = String(a).length; var lb = String(b).length; if (la < lb) return -1; else if (la > lb) return 1; else return 0; } shouldBe("var a = ['aa', 'b', 'cccc', 'ddd']; String(a.sort(comp))", "'b,aa,ddd,cccc'"); // +/-Infinity as function return value shouldBe("[0, Infinity].sort(function(a, b) { return a - b }).toString()", "'0,Infinity'"); // Array.unshift() shouldBe("[].unshift('a')", "1"); shouldBe("['c'].unshift('a', 'b')", "3"); shouldBe("var a = []; a.unshift('a'); String(a)", "'a'"); shouldBe("var a = ['c']; a.unshift('a', 'b'); String(a)", "'a,b,c'"); // Array.splice() shouldBe("String(['a', 'b', 'c'].splice(1, 2, 'x', 'y'))", "'b,c'"); var maxint = Math.pow(2,32)-1; var arr = new Array(); // 2^32 should not be treated as a valid array index, i.e. // setting the property on the array should not result in // the length being modified arr.length = 40; arr[maxint] = "test"; shouldBe("arr.length","40"); shouldBe("arr[maxint]","\"test\""); delete arr[maxint]; shouldBe("arr.length","40"); shouldBe("arr[maxint]","undefined"); arr[maxint-1] = "test2"; shouldBe("arr.length","maxint"); shouldBe("arr[maxint-1]","\"test2\""); // Floating point numbers also should not be treated as valid array indices. arr.length = 40; arr[55.5] = "test"; // does fit in a JSImmediate number arr[65.11111111111111111111111111111] = "test"; // does not fit in a JSImmediate number shouldBe("arr.length","40"); shouldBe("arr[55.5]","\"test\""); shouldBe("arr[65.11111111111111111111111111111]","\"test\""); delete arr[55.5]; delete arr[65.11111111111111111111111111111]; shouldBe("arr.length","40"); shouldBe("arr[55.5]","undefined"); shouldBe("arr[65.11111111111111111111111111111]","undefined"); arr = new Array('a','b','c'); arr.__proto__ = { 1: 'x' }; var propnames = new Array(); for (i in arr) propnames.push(i); propnames.sort(); shouldBe("propnames.length","3"); shouldBe("propnames[0]","'0'"); shouldBe("propnames[1]","'1'"); shouldBe("propnames[2]","'2'"); function testToString() { // backup var backupNumberToString = Number.prototype.toString; var backupNumberToLocaleString = Number.prototype.toLocaleString; var backupRegExpToString = RegExp.prototype.toString; var backupRegExpToLocaleString = RegExp.prototype.toLocaleString; // change functions Number.prototype.toString = function() { return "toString"; } Number.prototype.toLocaleString = function() { return "toLocaleString"; } RegExp.prototype.toString = function() { return "toString2"; } RegExp.prototype.toLocaleString = function() { return "toLocaleString2"; } // the tests shouldBe("[1].toString()", "'1'"); shouldBe("[1].toLocaleString()", "'toLocaleString'"); Number.prototype.toLocaleString = "invalid"; shouldBe("[1].toLocaleString()", "'1'"); shouldBe("[/r/].toString()", "'toString2'"); shouldBe("[/r/].toLocaleString()", "'toLocaleString2'"); RegExp.prototype.toLocaleString = "invalid"; shouldBe("[/r/].toLocaleString()", "'toString2'"); var caught = false; try { [{ toString : 0 }].toString(); } catch (e) { caught = true; } shouldBeTrue("caught"); // restore Number.prototype.toString = backupNumberToString; Number.prototype.toLocaleString = backupNumberToLocaleString; RegExp.prototype.toString = backupRegExpToString; RegExp.prototype.toLocaleString = backupRegExpToLocaleString; }