mirror of https://github.com/svaarala/duktape.git
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.
340 lines
17 KiB
340 lines
17 KiB
// XXX: 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);
|
|
}
|
|
|