1// Copyright 2013 the V8 project authors. All rights reserved.
2// Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions
6// are met:
7// 1.  Redistributions of source code must retain the above copyright
8//     notice, this list of conditions and the following disclaimer.
9// 2.  Redistributions in binary form must reproduce the above copyright
10//     notice, this list of conditions and the following disclaimer in the
11//     documentation and/or other materials provided with the distribution.
12//
13// THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16// DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
24description("KDE JS Test");
25// 15.4 Array Objects
26// (c) 2001 Harri Porten <porten@kde.org>
27
28shouldBe("Array().length", "0");
29shouldBe("(new Array()).length", "0");
30shouldBe("(new Array(3)).length", "3");
31shouldBe("(new Array(11, 22)).length", "2");
32shouldBe("(new Array(11, 22))[0]", "11");
33shouldBe("Array(11, 22)[1]", "22");
34shouldBeUndefined("(new Array(11, 22))[3]");
35shouldBe("String(new Array(11, 22))", "'11,22'");
36shouldBe("var a = []; a[0] = 33; a[0]", "33");
37shouldBe("var a = []; a[0] = 33; a.length", "1");
38shouldBe("var a = [11, 22]; a.length = 1; String(a);", "'11'");
39shouldBe("var a = [11, 22]; a.length = 1; a.length;", "1");
40
41// range checks
42var caught = false;
43var ename = "";
44try {
45  [].length = -1;
46} catch (e) {
47  // expect Range Error
48  caught = true;
49  ename = e.name;
50}
51
52shouldBeTrue("caught;");
53shouldBe("ename", "'RangeError'");
54
55caught = false;
56ename = "";
57try {
58  new Array(Infinity);
59} catch (e) {
60  // expect Range Error
61  caught = true;
62  ename = e.name;
63}
64shouldBeTrue("caught;");
65shouldBe("ename", "'RangeError'");
66
67shouldBeUndefined("var a = [11, 22]; a.length = 1; a[1];");
68shouldBe("Array().toString()", "''");
69shouldBe("Array(3).toString()", "',,'");
70shouldBe("Array(11, 22).toString()", "'11,22'");
71shouldBe("String(Array(11, 22).concat(33))", "'11,22,33'");
72shouldBe("String(Array(2).concat(33, 44))", "',,33,44'");
73shouldBe("String(Array(2).concat(Array(2)))", "',,,'");
74shouldBe("String(Array(11,22).concat(Array(33,44)))", "'11,22,33,44'");
75shouldBe("String(Array(1,2).concat(3,Array(4,5)))", "'1,2,3,4,5'");
76shouldBe("var a = new Array(1,2,3); delete a[1]; String(a.concat(4))", "'1,,3,4'");
77
78shouldBe("[1,2,3,4].slice(1, 3).toString()", "'2,3'");
79shouldBe("[1,2,3,4].slice(-3, -1).toString()", "'2,3'");
80shouldBe("[1,2].slice(-9, 0).length", "0");
81shouldBe("[1,2].slice(1).toString()", "'2'");
82shouldBe("[1,2].slice().toString()", "'1,2'");
83
84// 2nd set.
85shouldBe("(new Array('a')).length", "1");
86shouldBe("(new Array('a'))[0]", "'a'");
87shouldBeUndefined("(new Array('a'))[1]");
88
89shouldBe("Array('a').length", "1");
90shouldBe("Array('a')[0]", "'a'");
91
92shouldBe("String(Array())", "''");
93shouldBe("String(Array('a','b'))", "'a,b'");
94
95shouldBe("[].length", "0");
96shouldBe("['a'].length", "1");
97shouldBe("['a'][0]", "'a'");
98shouldBe("['a',,'c'][2]", "'c'");
99shouldBe("['a',undefined,'c'][1]", "undefined");
100shouldBe("['a',,'c'][1]", "undefined");
101shouldBe("1 in ['a',,'c']", "false");
102shouldBe("1 in ['a',undefined,'c']", "true");
103
104var arrayWithDeletion = ['a','b','c'];
105delete arrayWithDeletion[1];
106shouldBe("1 in arrayWithDeletion", "false");
107
108function forInSum(_a) {
109  var s = '';
110  for (i in _a)
111    s += _a[i];
112  return s;
113}
114
115shouldBe("forInSum([])", "''");
116shouldBe("forInSum(Array())", "''");
117shouldBe("forInSum(Array('a'))", "'a'");
118shouldBe("forInSum([,undefined,'x','aa'])", "'undefinedxaa'");
119
120var a0 = [];
121shouldBe("forInSum(a0)", "''");
122
123var a1 = [ 'a' ];
124shouldBe("forInSum(a1)", "'a'");
125
126shouldBe("String([].sort())", "''")
127shouldBe("String([3,1,'2'].sort())", "'1,2,3'");
128shouldBe("String([,'x','aa'].sort())", "'aa,x,'");
129shouldBe("String([,undefined,'x','aa'].sort())", "'aa,x,,'");
130shouldBe("2 in [,undefined,'x','aa'].sort()", "true");
131shouldBe("3 in [,undefined,'x','aa'].sort()", "false");
132
133// sort by length
134function comp(a, b) {
135  var la = String(a).length;
136  var lb = String(b).length;
137  if (la < lb)
138    return -1;
139  else if (la > lb)
140    return 1;
141  else
142    return 0;
143}
144shouldBe("var a = ['aa', 'b', 'cccc', 'ddd']; String(a.sort(comp))", "'b,aa,ddd,cccc'");
145
146// +/-Infinity as function return value
147shouldBe("[0, Infinity].sort(function(a, b) { return a - b }).toString()", "'0,Infinity'");
148
149// Array.unshift()
150shouldBe("[].unshift('a')", "1");
151shouldBe("['c'].unshift('a', 'b')", "3");
152shouldBe("var a = []; a.unshift('a'); String(a)", "'a'");
153shouldBe("var a = ['c']; a.unshift('a', 'b'); String(a)", "'a,b,c'");
154
155// Array.splice()
156shouldBe("String(['a', 'b', 'c'].splice(1, 2, 'x', 'y'))", "'b,c'");
157
158var maxint = Math.pow(2,32)-1;
159var arr = new Array();
160
161// 2^32 should not be treated as a valid array index, i.e.
162// setting the property on the array should not result in
163// the length being modified
164
165arr.length = 40;
166arr[maxint] = "test";
167shouldBe("arr.length","40");
168shouldBe("arr[maxint]","\"test\"");
169delete arr[maxint];
170shouldBe("arr.length","40");
171shouldBe("arr[maxint]","undefined");
172arr[maxint-1] = "test2";
173shouldBe("arr.length","maxint");
174shouldBe("arr[maxint-1]","\"test2\"");
175
176// Floating point numbers also should not be treated as valid array indices.
177arr.length = 40;
178arr[55.5] = "test"; // does fit in a JSImmediate number
179arr[65.11111111111111111111111111111] = "test"; // does not fit in a JSImmediate number
180shouldBe("arr.length","40");
181shouldBe("arr[55.5]","\"test\"");
182shouldBe("arr[65.11111111111111111111111111111]","\"test\"");
183delete arr[55.5];
184delete arr[65.11111111111111111111111111111];
185shouldBe("arr.length","40");
186shouldBe("arr[55.5]","undefined");
187shouldBe("arr[65.11111111111111111111111111111]","undefined");
188
189arr = new Array('a','b','c');
190arr.__proto__ = { 1: 'x' };
191var propnames = new Array();
192for (i in arr)
193  propnames.push(i);
194propnames.sort();
195shouldBe("propnames.length","3");
196shouldBe("propnames[0]","'0'");
197shouldBe("propnames[1]","'1'");
198shouldBe("propnames[2]","'2'");
199
200function testToString() {
201  // backup
202  var backupNumberToString = Number.prototype.toString;
203  var backupNumberToLocaleString = Number.prototype.toLocaleString;
204  var backupRegExpToString = RegExp.prototype.toString;
205  var backupRegExpToLocaleString = RegExp.prototype.toLocaleString;
206
207  // change functions
208  Number.prototype.toString = function() { return "toString"; }
209  Number.prototype.toLocaleString = function() { return "toLocaleString"; }
210  RegExp.prototype.toString = function() { return "toString2"; }
211  RegExp.prototype.toLocaleString = function() { return "toLocaleString2"; }
212
213  // the tests
214  shouldBe("[1].toString()", "'1'");
215  shouldBe("[1].toLocaleString()", "'toLocaleString'");
216  Number.prototype.toLocaleString = "invalid";
217  shouldBe("[1].toLocaleString()", "'1'");
218  shouldBe("[/r/].toString()", "'toString2'");
219  shouldBe("[/r/].toLocaleString()", "'toLocaleString2'");
220  RegExp.prototype.toLocaleString = "invalid";
221  shouldBe("[/r/].toLocaleString()", "'toString2'");
222
223  var caught = false;
224  try {
225    [{ toString : 0 }].toString();
226  } catch (e) {
227    caught = true;
228  }
229  shouldBeTrue("caught");
230
231  // restore
232  Number.prototype.toString = backupNumberToString;
233  Number.prototype.toLocaleString = backupNumberToLocaleString;
234  RegExp.prototype.toString = backupRegExpToString;
235  RegExp.prototype.toLocaleString = backupRegExpToLocaleString;
236}
237