You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

341 lines
17 KiB

// FIXME: these should be shared utils for Array testing
function dumpValue(v) {
var i, n, n_clipped;
var res = '';
if (v === undefined) {
return 'undefined';
} else if (v === null) {
return 'null';
}
n = v.length;
res = (typeof v) + ' ' + (typeof n) + ' ' + n;
if (typeof n === 'undefined') {
return res;
}
// clip dump length (n may be > 2**32)
n = Math.floor(n);
n_clipped = Math.min(n, 200);
tmp = [];
for (i = 0; i < n_clipped; i++) {
if (!v.hasOwnProperty(i)) {
tmp.push('nonexistent');
} else {
x = v[i];
tmp.push(typeof x + ':' + x);
}
}
res = res + (tmp.length > 0 ? ' ' + tmp.join(',') : '') + (n > n_clipped ? ',...' : '');
return res;
}
function test(this_value, loop_count) {
var t;
var pre, post, res;
if (loop_count === undefined) {
loop_count = 1;
}
while (loop_count-- > 0) {
pre = dumpValue(this_value);
try {
t = Array.prototype.pop.call(this_value);
res = typeof t + " " + t;
} catch (e) {
res = e.name;
}
post = dumpValue(this_value);
print(pre, '-->', res, '-->', post);
}
}
/*===
basic
object number 3 number:1,number:2,number:3 --> number 3 --> object number 2 number:1,number:2
object number 2 number:1,number:2 --> number 2 --> object number 1 number:1
object number 1 number:1 --> number 1 --> object number 0
object number 0 --> undefined undefined --> object number 0
object number 0 --> undefined undefined --> object number 0
object number 4 number:1,nonexistent,nonexistent,number:2 --> number 2 --> object number 3 number:1,nonexistent,nonexistent
object number 3 number:1,nonexistent,nonexistent --> undefined undefined --> object number 2 number:1,nonexistent
object number 2 number:1,nonexistent --> undefined undefined --> object number 1 number:1
object number 1 number:1 --> number 1 --> object number 0
object number 0 --> undefined undefined --> object number 0
object number 0 --> undefined undefined --> object number 0
object number 11 number:1,nonexistent,nonexistent,nonexistent,nonexistent,number:2,nonexistent,nonexistent,nonexistent,nonexistent,number:3 --> number 3 --> object number 10 number:1,nonexistent,nonexistent,nonexistent,nonexistent,number:2,nonexistent,nonexistent,nonexistent,nonexistent
object number 10 number:1,nonexistent,nonexistent,nonexistent,nonexistent,number:2,nonexistent,nonexistent,nonexistent,nonexistent --> undefined undefined --> object number 9 number:1,nonexistent,nonexistent,nonexistent,nonexistent,number:2,nonexistent,nonexistent,nonexistent
object number 9 number:1,nonexistent,nonexistent,nonexistent,nonexistent,number:2,nonexistent,nonexistent,nonexistent --> undefined undefined --> object number 8 number:1,nonexistent,nonexistent,nonexistent,nonexistent,number:2,nonexistent,nonexistent
object number 8 number:1,nonexistent,nonexistent,nonexistent,nonexistent,number:2,nonexistent,nonexistent --> undefined undefined --> object number 7 number:1,nonexistent,nonexistent,nonexistent,nonexistent,number:2,nonexistent
object number 7 number:1,nonexistent,nonexistent,nonexistent,nonexistent,number:2,nonexistent --> undefined undefined --> object number 6 number:1,nonexistent,nonexistent,nonexistent,nonexistent,number:2
object number 6 number:1,nonexistent,nonexistent,nonexistent,nonexistent,number:2 --> number 2 --> object number 5 number:1,nonexistent,nonexistent,nonexistent,nonexistent
object number 5 number:1,nonexistent,nonexistent,nonexistent,nonexistent --> undefined undefined --> object number 4 number:1,nonexistent,nonexistent,nonexistent
object number 4 number:1,nonexistent,nonexistent,nonexistent --> undefined undefined --> object number 3 number:1,nonexistent,nonexistent
object number 3 number:1,nonexistent,nonexistent --> undefined undefined --> object number 2 number:1,nonexistent
object number 2 number:1,nonexistent --> undefined undefined --> object number 1 number:1
object number 1 number:1 --> number 1 --> object number 0
object number 0 --> undefined undefined --> object number 0
object number 0 --> undefined undefined --> object number 0
object number 3 number:1,string:2-undel,number:3 --> number 3 --> object number 2 number:1,string:2-undel
object number 2 number:1,string:2-undel --> TypeError --> object number 2 number:1,string:2-undel
object number 2 number:1,string:2-undel --> TypeError --> object number 2 number:1,string:2-undel
object number 2 number:1,string:2-undel --> TypeError --> object number 2 number:1,string:2-undel
object string 10 string:first,string:second,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent --> undefined undefined --> object number 9 string:first,string:second,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent
object number 9 string:first,string:second,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent --> undefined undefined --> object number 8 string:first,string:second,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent
object number 8 string:first,string:second,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent --> undefined undefined --> object number 7 string:first,string:second,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent
object number 7 string:first,string:second,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent --> undefined undefined --> object number 6 string:first,string:second,nonexistent,nonexistent,nonexistent,nonexistent
object number 6 string:first,string:second,nonexistent,nonexistent,nonexistent,nonexistent --> undefined undefined --> object number 5 string:first,string:second,nonexistent,nonexistent,nonexistent
object number 5 string:first,string:second,nonexistent,nonexistent,nonexistent --> undefined undefined --> object number 4 string:first,string:second,nonexistent,nonexistent
object number 4 string:first,string:second,nonexistent,nonexistent --> undefined undefined --> object number 3 string:first,string:second,nonexistent
object number 3 string:first,string:second,nonexistent --> undefined undefined --> object number 2 string:first,string:second
object number 2 string:first,string:second --> string second --> object number 1 string:first
object number 1 string:first --> string first --> object number 0
object number 0 --> undefined undefined --> object number 0
object number 0 --> undefined undefined --> object number 0
===*/
print('basic');
function basicTest() {
var t;
// dense array
t = [1,2,3];
test(t, 5);
t = [1,,,2];
test(t, 6);
// sparse array
t = [1];
t[100] = 'x'; // use this to get into 'sparse mode' but use smaller length to minimize output
t.length = 1;
t[10] = 3;
t[5] = 2;
test(t, 13);
// non-deletable element
t = [ 1, 2, 3 ];
Object.defineProperties(t, {
'1': { value: '2-undel', writable: false, enumerable: true, configurable: false }
});
test(t, 4);
// trailing non-existent elements
t = { '0': 'first', '1': 'second', length: '10' };
test(t, 12);
}
try {
basicTest();
} catch (e) {
print(e);
}
/*===
coercion
undefined --> TypeError --> undefined
null --> TypeError --> null
boolean undefined undefined --> undefined undefined --> boolean undefined undefined
boolean undefined undefined --> undefined undefined --> boolean undefined undefined
number undefined undefined --> undefined undefined --> number undefined undefined
string number 3 string:f,string:o,string:o --> TypeError --> string number 3 string:f,string:o,string:o
string number 3 string:f,string:o,string:o --> TypeError --> string number 3 string:f,string:o,string:o
string number 3 string:f,string:o,string:o --> TypeError --> string number 3 string:f,string:o,string:o
string number 3 string:f,string:o,string:o --> TypeError --> string number 3 string:f,string:o,string:o
object number 2 number:1,number:2 --> number 2 --> object number 1 number:1
object undefined undefined --> undefined undefined --> object number 0
object number 2 string:foo,string:bar --> string bar --> object number 1 string:foo
object string 0.9 --> undefined undefined --> object number 0
object number 5 string:first,string:second,nonexistent,nonexistent,nonexistent --> undefined undefined --> object number 4 string:first,string:second,nonexistent,nonexistent
object number 4 string:first,string:second,nonexistent,nonexistent --> undefined undefined --> object number 3 string:first,string:second,nonexistent
object number 3 string:first,string:second,nonexistent --> undefined undefined --> object number 2 string:first,string:second
object number 2 string:first,string:second --> string second --> object number 1 string:first
object number 1 string:first --> string first --> object number 0
object number 0 --> undefined undefined --> object number 0
object number 0 --> undefined undefined --> object number 0
object number 4294967301 string:first,string:second,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,nonexistent,... --> undefined undefined --> object number 4 string:first,string:second,nonexistent,nonexistent
object number 4 string:first,string:second,nonexistent,nonexistent --> undefined undefined --> object number 3 string:first,string:second,nonexistent
object number 3 string:first,string:second,nonexistent --> undefined undefined --> object number 2 string:first,string:second
object number 2 string:first,string:second --> string second --> object number 1 string:first
object number 1 string:first --> string first --> object number 0
object number 0 --> undefined undefined --> object number 0
object number 0 --> undefined undefined --> object number 0
length getter 3
1 getter
length getter 3
length setter 2
length getter 2
1 getter
object number 3 string:foo,string:bar,nonexistent --> undefined undefined --> object number 2 string:foo,string:bar
length getter 2
1 getter
length getter 2
1 getter
length setter 1
length getter 1
object number 2 string:foo,string:bar --> string bar --> object number 1 string:foo
length getter 1
length getter 1
length setter 0
length getter 0
object number 1 string:foo --> string foo --> object number 0
length getter 0
length getter 0
length setter 0
length getter 0
object number 0 --> undefined undefined --> object number 0
length getter 0
length getter 0
length setter 0
length getter 0
object number 0 --> undefined undefined --> object number 0
===*/
print('coercion');
function coercionTest() {
// this coercion
test(undefined);
test(null);
test(true);
test(false);
test(123);
test('foo', 4); // character are non-configurable
test([1,2]);
test({ foo: 1, bar: 2 });
test({ '0': 'foo', '1': 'bar', length: 2 });
// ToUint32('0.9') -> coerces to zero, return undefined, length will be written to number 0
t = { length: '0.9' };
test(t);
// length goes through ToUint32(), so these should have no difference
// (V8 3.7.12.22 seems to iterate through 4G elements here)
t = { '0': 'first', '1': 'second', length: 5 };
test(t, 7);
t = { '0': 'first', '1': 'second', length: 256*256*256*256 + 5 };
test(t, 7);
// complex test with lots of side effect checks
// note that pre/post printing confuses the output a bit
t = Object.create(Object.prototype, {
'0': {
value: 'foo',
writable: true,
enumerable: true,
configurable: true
},
'1': {
get: function() {
print('1 getter');
return 'bar';
},
set: function() {
print('1 setter');
},
enumerable: true,
configurable: true
},
'length': {
get: function() {
print('length getter', this.mylen);
return this.mylen;
},
set: function(v) {
print('length setter', v);
this.mylen = v;
},
enumerable: true,
configurable: true
}
});
t.mylen = 3;
test(t, 5);
}
try {
coercionTest();
} catch (e) {
print(e);
}
/*===
delete/put prevented
object string 0 --> TypeError --> object string 0
object string 2 nonexistent,nonexistent --> TypeError --> object string 2 nonexistent,nonexistent
string number 3 string:f,string:o,string:o --> TypeError --> string number 3 string:f,string:o,string:o
object number 2 string:foo,string:bar --> TypeError --> object number 2 string:foo,string:bar
object number 2 string:foo,string:bar --> TypeError --> object number 2 string:foo,string:bar
object number 2 string:foo,string:bar --> TypeError --> object number 2 string:foo,string:bar
object number 2 string:foo,string:bar --> TypeError --> object number 2 string:foo,string:bar
object number 2 string:foo,string:bar --> TypeError --> object number 2 string:foo,string:bar
object number 2 string:foo,string:bar --> TypeError --> object number 2 string:foo,string:bar
===*/
/* Attempt to [[Delete]] entries or [[Put]] to "length" have the "Throw" flag
* set in both non-strict and strict mode. If attributes prevent deletion or
* writing, a TypeError must result even in non-strict mode.
*/
print('delete/put prevented');
function deleteOrPutPreventedTest() {
var t;
// Length is zero and non-writable
t = Object.create(Object.prototype, {
'length': { value: '0', writable: false, enumerable: true, configurable: true }
});
test(t, 1);
// Length is non-zero and non-writable
t = Object.create(Object.prototype, {
'length': { value: '2', writable: false, enumerable: true, configurable: true }
});
test(t, 1);
// Characters are non-configurable, which causes [[Delete]] to fail
test('foo', 1);
// Same for this object; because the [[Put]] should fail with TypeError,
// the (writable) length should not be updated
t = Object.create(Object.prototype, {
'0': { value: 'foo', writable: false, enumerable: true, configurable: false },
'1': { value: 'bar', writable: false, enumerable: true, configurable: false },
'length': { value: 2, writable: true, enumerable: true, configurable: true }
});
test(t, 3);
// Length is not writable either but should have no effect, TypeError on attempt to [[Delete]] "1"
t = Object.create(Object.prototype, {
'0': { value: 'foo', writable: false, enumerable: true, configurable: false },
'1': { value: 'bar', writable: false, enumerable: true, configurable: false },
'length': { value: 2, writable: false, enumerable: true, configurable: false }
});
test(t, 3);
}
try {
deleteOrPutPreventedTest();
} catch (e) {
print(e);
}