JDK-8035312.js revision 1101:be3f5ca1edbf
1169691Skan/*
2169691Skan * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
3169691Skan * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4169691Skan *
5169691Skan * This code is free software; you can redistribute it and/or modify it
6169691Skan * under the terms of the GNU General Public License version 2 only, as
7169691Skan * published by the Free Software Foundation.
8169691Skan *
9169691Skan * This code is distributed in the hope that it will be useful, but WITHOUT
10169691Skan * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11169691Skan * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12169691Skan * version 2 for more details (a copy is included in the LICENSE file that
13169691Skan * accompanied this code).
14169691Skan *
15169691Skan * You should have received a copy of the GNU General Public License version
16169691Skan * 2 along with this work; if not, write to the Free Software Foundation,
17169691Skan * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18169691Skan *
19169691Skan * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20169691Skan * or visit www.oracle.com if you need additional information or have any
21169691Skan * questions.
22169691Skan */
23169691Skan
24169691Skan/**
25169691Skan * JDK-8035312 push to frozen array must not increase length property
26169691Skan *
27169691Skan * @test
28169691Skan * @run
29169691Skan * @fork
30169691Skan * @option -Dnashorn.debug=true
31169691Skan */
32169691Skan
33169691Skanfunction printArrayDataClass(x) {
34169691Skan    if (typeof Debug !== 'undefined') {
35169691Skan	print(Debug.getArrayDataClass(x));
36169691Skan    }
37169691Skan}
38169691Skan
39169691Skanfunction gpush(x, elem) {
40169691Skan    try {
41169691Skan	print("Pushing " + elem + " to " + x);
42169691Skan	x.push(elem);
43169691Skan    } catch (e) {
44169691Skan	print("caught error" + e);
45169691Skan    }
46169691Skan    print("\tarray is now [" + x + "] length is = " + x.length);
47169691Skan    print();
48169691Skan    printArrayDataClass(x);
49169691Skan}
50169691Skan
51169691Skanfunction gpop(x) {
52169691Skan    try {
53169691Skan	print("Popping from " + x);
54169691Skan	x.pop();
55169691Skan    } catch (e) {
56169691Skan	if (!(e instanceof TypeError)) {
57169691Skan	    print("e of wrong type " + e);
58169691Skan	}
59169691Skan    }
60169691Skan    print("\tarray is now [" + x + "] length is = " + x.length);
61169691Skan    print();
62169691Skan    printArrayDataClass(x);
63169691Skan}
64169691Skan
65169691Skanfunction checkArray(x) {
66169691Skan    print();
67169691Skan    print(">>> Push test");
68169691Skan
69169691Skan    var olen = x.length;
70169691Skan    gpush(x, 0);
71169691Skan
72169691Skan    print("x.length === " + x.length + " (should be " + olen + ")");
73169691Skan    print("x[3] === " + x[3] + " (should be 0)");
74169691Skan    print("x[4] === " + x[4] + " (should be undefined)");
75169691Skan
76169691Skan    print();
77169691Skan    print(">>> Pop test");
78169691Skan    gpop(x);
79169691Skan    gpop(x);
80169691Skan    print("x.length === " + x.length + " (should be " + olen + ")");
81169691Skan    print("x === " + x);
82169691Skan
83169691Skan    for (var i = 0 ; i < 5; i++) {
84169691Skan	gpop(x);
85169691Skan    }
86169691Skan
87169691Skan    print("x.length === " + x.length + " (should be " + olen + ")");
88169691Skan    print("x === " + x);
89169691Skan}
90169691Skan
91169691Skanprint("*** Freezing");
92169691Skanvar frozen = [1,2,3];
93169691SkanObject.freeze(frozen);
94169691SkancheckArray(frozen);
95169691SkanprintArrayDataClass(frozen);
96169691Skan
97169691Skan//so far so good
98169691Skan
99169691Skanprint();
100169691Skanprint("*** Other length not writable issues");
101169691Skanvar lengthNotWritable = [1,2,3];
102169691SkanObject.defineProperty(lengthNotWritable, "length", { writable: false });
103169691SkancheckArray(lengthNotWritable);
104169691SkanprintArrayDataClass(lengthNotWritable);
105169691Skan
106169691Skanfunction set(array, from, to, stride) {
107169691Skan    //add three elements
108169691Skan    for (var i = from; i < to; i+=stride) {
109169691Skan	try {
110169691Skan	    print("Writing " + i);
111169691Skan	    array[i] = i;
112169691Skan	    printArrayDataClass(array);
113169691Skan	} catch (e) {
114169691Skan	    print(e instanceof TypeError);
115169691Skan	}
116169691Skan    }
117169691Skan}
118169691Skan
119169691Skan//define empty array with non writable length
120169691Skanvar arr = [1];
121169691SkanObject.defineProperty(arr, "length", { writable: false });
122169691Skan
123169691Skanvar olen2 = arr.length;
124169691Skan
125169691Skanset(arr, 0, 3, 1);
126169691Skan
127169691Skanif (arr.length != olen2) {
128169691Skan    throw new ("error: " +  arr.length + " != " + olen2);
129169691Skan}
130169691Skan
131print();
132print("array writing 0-3, with 1 stride, array = " + arr);
133print("length = " + arr.length + ", but elements are: " + arr[0] + " " + arr[1] + " " + arr[2]);
134print();
135
136//do the same but sparse/deleted range
137var arr2 = [1];
138Object.defineProperty(arr2, "length", { writable: false });
139
140print("initial length = " + arr2.length);
141var olen3 = arr2.length;
142
143set(arr2, 0, 30, 3);
144
145if (arr2.length != olen3) {
146    throw new ("error: " +  arr2.length + " != " + olen3);
147}
148
149print();
150var larger = 20;
151print("array writing 0-" + larger + ", with 3 stride, array = " + arr2);
152print("length = " + arr2.length + ", but elements are: " + arr2[0] + " " + arr2[1] + " " + arr2[2]);
153
154for (var i = 0; i < larger; i++) {
155    if (arr2[i] === undefined) {
156	continue;
157    }
158    print(arr2[i] + " has length " + arr2.length);
159}
160
161print();
162var elem = 0x7fffffff - 10;
163printArrayDataClass(arr2);
164print("adding a new element high up in the array");
165print("length before element was added " + arr2.length);
166print("putting sparse at " + elem);
167arr2[elem] = "sparse";
168print("length after element was added " + arr2.length + " should be the same");
169printArrayDataClass(arr2);
170
171print();
172print("Printing arr2 - this will fail if length is > 28 and it is " + arr2.length);
173print("arr2 = [" + arr2 + "]");
174print("new length that should not be writable = " + arr2.length);
175print(arr2[elem] === "sparse");
176print(arr2[elem]);
177for (var i = 0; i < larger; i++) {
178    print(arr2[i]);
179}
180for (var key in arr2) {
181    print(key + ":" + arr2[key]);
182}
183
184//issues reported by sundar - generic setter doesn't go through push/pop bulkable
185
186function sundarExample2(arr, _writable) {
187    print("Checking if push works for bulkable non bulkable arrays - Setting length property not allowed");
188    arr[0] = "bar";
189    print(arr.length + " should be 1"); // should be 1
190    print(arr[0] + " should be bar");
191    print("["+ arr + "] should be [bar]");
192
193    //    Object.defineProperty(arr, "length", { configurable: _writable });
194    Object.defineProperty(arr, "length", { writable: _writable });
195    arr[1] = "baz";
196
197    if (_writable) {
198	print(arr.length + " should be 2");
199	print(arr[0] + " should be bar");
200	print(arr[1] + " should be baz");
201	print("["+ arr + "] should be [bar,baz]");
202    } else {
203	print(arr.length + " should STILL be 1");
204	print(arr[0] + " should be bar");
205	print(arr[1] + " should be baz");
206	print("["+ arr + "] should be [bar]");
207    }
208}
209
210var newArr1 = [];
211sundarExample2(newArr1, false);
212print();
213try {
214    sundarExample2(newArr1, true);
215    print("should not get here");
216} catch (e) {
217    if (!(e instanceof TypeError)) {
218	print("Wrong exception");
219    }
220    print("got TypeError when redefining length, as expected")
221}
222print();
223
224sundarExample2([], true);
225print("Done");
226