ai_old/goja/builtin_arrray_test.go

368 lines
9.1 KiB
Go
Raw Normal View History

2024-09-20 16:50:35 +08:00
package goja
import (
"testing"
)
func TestArrayProtoProp(t *testing.T) {
const SCRIPT = `
Object.defineProperty(Array.prototype, '0', {value: 42, configurable: true, writable: false})
var a = []
a[0] = 1
a[0]
`
testScript(SCRIPT, valueInt(42), t)
}
func TestArrayDelete(t *testing.T) {
const SCRIPT = `
var a = [1, 2];
var deleted = delete a[0];
var undef = a[0] === undefined;
var len = a.length;
deleted && undef && len === 2;
`
testScript(SCRIPT, valueTrue, t)
}
func TestArrayDeleteNonexisting(t *testing.T) {
const SCRIPT = `
Array.prototype[0] = 42;
var a = [];
delete a[0] && a[0] === 42;
`
testScript(SCRIPT, valueTrue, t)
}
func TestArraySetLength(t *testing.T) {
const SCRIPT = `
var a = [1, 2];
var assert0 = a.length == 2;
a.length = "1";
a.length = 1.0;
a.length = 1;
var assert1 = a.length == 1;
a.length = 2;
var assert2 = a.length == 2;
assert0 && assert1 && assert2 && a[1] === undefined;
`
testScript(SCRIPT, valueTrue, t)
}
func TestArrayReverseNonOptimisable(t *testing.T) {
const SCRIPT = `
var a = [];
Object.defineProperty(a, "0", {get: function() {return 42}, set: function(v) {Object.defineProperty(a, "0", {value: v + 1, writable: true, configurable: true})}, configurable: true})
a[1] = 43;
a.reverse();
a.length === 2 && a[0] === 44 && a[1] === 42;
`
testScript(SCRIPT, valueTrue, t)
}
func TestArrayPushNonOptimisable(t *testing.T) {
const SCRIPT = `
Object.defineProperty(Object.prototype, "0", {value: 42});
var a = [];
var thrown = false;
try {
a.push(1);
} catch (e) {
thrown = e instanceof TypeError;
}
thrown;
`
testScript(SCRIPT, valueTrue, t)
}
func TestArraySetLengthWithPropItems(t *testing.T) {
const SCRIPT = `
var a = [1,2,3,4];
var thrown = false;
Object.defineProperty(a, "2", {value: 42, configurable: false, writable: false});
try {
Object.defineProperty(a, "length", {value: 0, writable: false});
} catch (e) {
thrown = e instanceof TypeError;
}
thrown && a.length === 3;
`
testScript(SCRIPT, valueTrue, t)
}
func TestArrayFrom(t *testing.T) {
const SCRIPT = `
function checkDestHoles(dest, prefix) {
assert(dest !== source, prefix + ": dest !== source");
assert.sameValue(dest.length, 3, prefix + ": dest.length");
assert.sameValue(dest[0], 1, prefix + ": [0]");
assert.sameValue(dest[1], undefined, prefix + ": [1]");
assert(dest.hasOwnProperty("1"), prefix + ': hasOwnProperty("1")');
assert.sameValue(dest[2], 3, prefix + ": [2]");
}
function checkDest(dest, prefix) {
assert(dest !== source, prefix + ": dest !== source");
assert.sameValue(dest.length, 3, prefix + ": dest.length");
assert.sameValue(dest[0], 1, prefix + ": [0]");
assert.sameValue(dest[1], 2, prefix + ": [1]");
assert.sameValue(dest[2], 3, prefix + ": [2]");
}
var source = [1,2,3];
var srcHoles = [1,,3];
checkDest(Array.from(source), "std source/std dest");
checkDestHoles(Array.from(srcHoles), "std source (holes)/std dest");
function Iter() {
this.idx = 0;
}
Iter.prototype.next = function() {
if (this.idx < source.length) {
return {value: source[this.idx++]};
} else {
return {done: true};
}
}
var src = {};
src[Symbol.iterator] = function() {
return new Iter();
}
checkDest(Array.from(src), "iter src/std dest");
src = {0: 1, 2: 3, length: 3};
checkDestHoles(Array.from(src), "arrayLike src/std dest");
function A() {}
A.from = Array.from;
checkDest(A.from(source), "std src/cust dest");
checkDestHoles(A.from(srcHoles), "std src (holes)/cust dest");
checkDestHoles(A.from(src), "arrayLike src/cust dest");
function T2() {
Object.defineProperty(this, 0, {
configurable: false,
writable: true,
enumerable: true
});
}
assert.throws(TypeError, function() {
Array.from.call(T2, source);
});
`
testScriptWithTestLib(SCRIPT, _undefined, t)
}
func TestArrayOf(t *testing.T) {
const SCRIPT = `
function T1() {
Object.preventExtensions(this);
}
assert.throws(TypeError, function() {
Array.of.call(T1, 'Bob');
});
function T2() {
Object.defineProperty(this, 0, {
configurable: false,
writable: true,
enumerable: true
});
}
assert.throws(TypeError, function() {
Array.of.call(T2, 'Bob');
})
result = Array.of.call(undefined);
assert(
result instanceof Array,
'this is not a constructor'
);
result = Array.of.call(Math.cos);
assert(
result instanceof Array,
'this is a builtin function with no [[Construct]] slot'
);
`
testScriptWithTestLib(SCRIPT, _undefined, t)
}
func TestUnscopables(t *testing.T) {
const SCRIPT = `
var keys = [];
var _length;
with (Array.prototype) {
_length = length;
keys.push('something');
}
_length === 0 && keys.length === 1 && keys[0] === "something";
`
testScript(SCRIPT, valueTrue, t)
}
func TestArraySort(t *testing.T) {
const SCRIPT = `
assert.throws(TypeError, function() {
[1,2].sort(null);
}, "null compare function");
assert.throws(TypeError, function() {
[1,2].sort({});
}, "non-callable compare function");
`
testScriptWithTestLib(SCRIPT, _undefined, t)
}
func TestArraySortNonStdArray(t *testing.T) {
const SCRIPT = `
const array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
Object.defineProperty(array, '2', {
get() {
array.pop();
array.pop();
return this.foo;
},
set(v) {
this.foo = v;
}
});
array.sort();
assert.sameValue(array[0], 'b');
assert.sameValue(array[1], 'c');
assert.sameValue(array[3], undefined);
assert.sameValue(array[4], undefined);
assert.sameValue('5' in array, false);
assert.sameValue(array.hasOwnProperty('5'), false);
assert.sameValue(array.length, 6);
assert.sameValue(array.foo, undefined);
assert.sameValue(array[2], undefined);
assert.sameValue(array.length, 4);
`
testScriptWithTestLib(SCRIPT, _undefined, t)
}
func TestArrayConcat(t *testing.T) {
const SCRIPT = `
var concat = Array.prototype.concat;
var array = [1, 2];
var sparseArray = [1, , 2];
var nonSpreadableArray = [1, 2];
nonSpreadableArray[Symbol.isConcatSpreadable] = false;
var arrayLike = { 0: 1, 1: 2, length: 2 };
var spreadableArrayLike = { 0: 1, 1: 2, length: 2 };
spreadableArrayLike[Symbol.isConcatSpreadable] = true;
assert(looksNative(concat));
assert(deepEqual(array.concat(), [1, 2]), '#1');
assert(deepEqual(sparseArray.concat(), [1, , 2]), '#2');
assert(deepEqual(nonSpreadableArray.concat(), [[1, 2]]), '#3');
assert(deepEqual(concat.call(arrayLike), [{ 0: 1, 1: 2, length: 2 }]), '#4');
assert(deepEqual(concat.call(spreadableArrayLike), [1, 2]), '#5');
assert(deepEqual([].concat(array), [1, 2]), '#6');
assert(deepEqual([].concat(sparseArray), [1, , 2]), '#7');
assert(deepEqual([].concat(nonSpreadableArray), [[1, 2]]), '#8');
assert(deepEqual([].concat(arrayLike), [{ 0: 1, 1: 2, length: 2 }]), '#9');
assert(deepEqual([].concat(spreadableArrayLike), [1, 2]), '#10');
assert(deepEqual(array.concat(sparseArray, nonSpreadableArray, arrayLike, spreadableArrayLike), [
1, 2, 1, , 2, [1, 2], { 0: 1, 1: 2, length: 2 }, 1, 2,
]), '#11');
array = [];
array.constructor = {};
array.constructor[Symbol.species] = function () {
return { foo: 1 };
}
assert.sameValue(array.concat().foo, 1, '@@species');
`
testScriptWithTestLibX(SCRIPT, _undefined, t)
}
func TestArrayFlat(t *testing.T) {
const SCRIPT = `
var array = [1, [2,3,[4,5,6]], [[[[7,8,9]]]]];
assert(deepEqual(array.flat(), [1,2,3,[4,5,6],[[[7,8,9]]]]), '#1');
assert(deepEqual(array.flat(1), [1,2,3,[4,5,6],[[[7,8,9]]]]), '#2');
assert(deepEqual(array.flat(3), [1,2,3,4,5,6,[7,8,9]]), '#3');
assert(deepEqual(array.flat(4), [1,2,3,4,5,6,7,8,9]), '#4');
assert(deepEqual(array.flat(10), [1,2,3,4,5,6,7,8,9]), '#5');
`
testScriptWithTestLibX(SCRIPT, _undefined, t)
}
func TestArrayFlatMap(t *testing.T) {
const SCRIPT = `
var double = function(x) {
if (isNaN(x)) {
return x
}
return x * 2
}
var array = [1, [2,3,[4,5,6]], [[[[7,8,9]]]]];
assert(deepEqual(array.flatMap(double), [2,2,3,[4,5,6],[[[7,8,9]]]]), '#1');
`
testScriptWithTestLibX(SCRIPT, _undefined, t)
}
func TestArrayProto(t *testing.T) {
const SCRIPT = `
const a = Array.prototype;
a.push(1, 2, 3, 4, 5);
assert.sameValue(a.length, 5);
assert.sameValue(a[0], 1);
a.length = 3;
assert.sameValue(a.length, 3);
assert(compareArray(a, [1, 2, 3]));
a.shift();
assert.sameValue(a.length, 2);
assert(compareArray(a, [2, 3]));
`
testScriptWithTestLib(SCRIPT, _undefined, t)
}
func TestArrayToSpliced(t *testing.T) {
const SCRIPT = `
const a = [1, 2, 3];
a.push(4)
assert(compareArray(a, [1, 2, 3, 4]));
const b = a.toSpliced(2)
assert(compareArray(a, [1, 2, 3, 4]));
assert(compareArray(b, [1, 2]));
a.push(5)
const c = a.toSpliced(1, 2);
assert(compareArray(a, [1, 2, 3, 4, 5]));
assert(compareArray(c, [1, 4, 5]));
assert(compareArray(a.toSpliced(4, 2, 'a', 'b'), [1, 2, 3, 4, 'a', 'b']));
assert(compareArray(a, [1, 2, 3, 4, 5]));
assert(compareArray(a.toSpliced(-2, 2), [1, 2, 3]));
assert(compareArray(a, [1, 2, 3, 4, 5]));
assert(compareArray(a.toSpliced(2, 10), [1, 2]));
assert(compareArray(a, [1, 2, 3, 4, 5]));
assert(compareArray(a.toSpliced(1, 0, 'a'), [1, 'a', 2, 3, 4, 5]));
assert(compareArray(a, [1, 2, 3, 4, 5]));
`
testScriptWithTestLib(SCRIPT, _undefined, t)
}