<!DOCTYPE html>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script>
function createIterable(iterations) {
return {
[Symbol.iterator]() {
var i = 0;
return {next: () => iterations[i++]};
},
};
}
test(() => {
let sequenceTest = internals.sequenceTest();
assert_throws_js(TypeError, () => { sequenceTest.identityLongSequence(null) },
"Converting null to sequence must throw a type error");
assert_throws_js(TypeError, () => { sequenceTest.identityLongSequence(undefined) },
"Converting undefined to sequence must throw a type error");
assert_equals(sequenceTest.identityOctetSequenceOrNull(null), null,
"Converting null to a nullable sequence works");
assert_equals(sequenceTest.identityOctetSequenceOrNull(undefined), null,
"Converting undefined to a nullable sequence works");
}, "null and undefined conversions");
test(() => {
let sequenceTest = internals.sequenceTest();
let emptyArray = [];
let emptyObject = createIterable([{done: true}]);
let convertedArray = sequenceTest.identityLongSequence(emptyArray);
assert_array_equals(convertedArray, [], "Empty array produces an empty vector");
let convertedObject = sequenceTest.identityLongSequence(emptyObject);
assert_array_equals(convertedObject, [], "Empty object produces an empty vector");
}, "Empty sequences");
test(() => {
let sequenceTest = internals.sequenceTest();
let obj = createIterable([
{ done: false, value: 34 },
{ done: false, value: 42 },
{ done: true }
]);
let convertedObj = sequenceTest.identityLongSequence(obj);
assert_array_equals(convertedObj, [34, 42],
"'done: true' does not need a value property");
obj = createIterable([
{ done: false, value: 34 },
{ done: false, value: 42 },
{ done: true, value: 88 }
]);
convertedObj = sequenceTest.identityLongSequence(obj);
assert_array_equals(convertedObj, [34, 42],
"'value' is ignored when 'done' is true");
obj = createIterable([
{ done: 0, value: 42 },
{ done: 1, value: 34 }
]);
convertedObj = sequenceTest.identityDoubleSequence(obj);
assert_array_equals(convertedObj, [42],
"'done' is always converted to a boolean");
}, "Iterator stop values");
test(() => {
let sequenceTest = internals.sequenceTest();
let array = [1, 2];
let convertedArray = sequenceTest.identityDoubleSequence(array);
assert_not_equals(array, convertedArray);
convertedArray.push(42);
let convertedArray2 = sequenceTest.identityDoubleSequence(array);
assert_equals(array.length, 2);
assert_not_equals(convertedArray, convertedArray2);
assert_array_equals(convertedArray2, [1, 2]);
}, "Sequences are passed by value");
test(() => {
let sequenceTest = internals.sequenceTest();
let longArray = ['not', 'a', 'long'];
longArray[5] = 42;
let convertedLongArray = sequenceTest.identityLongSequence(longArray);
assert_array_equals(convertedLongArray, [0, 0, 0, 0, 0, 42],
"Long array with gaps correctly produces a vector");
let doubleArray = [34, 42.5];
doubleArray[9] = 2; // The elements inbetween are all undefined.
assert_throws_js(TypeError, () => { sequenceTest.identityDoubleSequence(doubleArray) },
"Converting an undefined value to double throws a TypeError and " +
"causes the sequence -> C++ conversion to fail");
let byteStringSequenceSequence = [
["foo"],
["bar"]
];
byteStringSequenceSequence[7] = ["baz"];
assert_throws_js(TypeError, () => {
sequenceTest.identityByteStringSequenceSequence(byteStringSequenceSequence);
}, "Converting an undefined to a sequence<> throws a TypeError and causes the " +
"entire conversion to fail");
}, "Arrays with gaps in the elements");
test(() => {
let sequenceTest = internals.sequenceTest();
assert_throws_js(TypeError, () => { sequenceTest.identityLongSequence({}) },
"Objects without Symbol.iterator cannot be converted");
let obj = {
[Symbol.iterator]: 42
};
assert_throws_js(TypeError, () => { sequenceTest.identityLongSequence(obj) },
"Symbol.iterator must be callable");
obj = {
[Symbol.iterator]() {
return 42;
}
}
assert_throws_js(TypeError, () => { sequenceTest.identityLongSequence(obj) },
"Symbol.iterator must return an object");
obj = {
[Symbol.iterator]() {
return {}
}
}
assert_throws_js(TypeError, () => { sequenceTest.identityLongSequence(obj) },
"Symbol.iterator must return an object with a 'next' callable");
obj = {
[Symbol.iterator]() {
return {'next': 42}
}
}
assert_throws_js(TypeError, () => { sequenceTest.identityLongSequence(obj) },
"Symbol.iterator must return an object with a 'next' callable");
obj = {
[Symbol.iterator]() {
return {'next': () => { return 42 }}
}
}
assert_throws_js(TypeError, () => { sequenceTest.identityLongSequence(obj) },
"'next' must return an object");
}, "Invalid iterable protocols");
test(() => {
let sequenceTest = internals.sequenceTest();
assert_false(sequenceTest.unionReceivedSequence(42),
"Passing a double should convert the union to double");
assert_false(sequenceTest.unionReceivedSequence(true),
"Passing a boolean should convert the union to double");
assert_true(sequenceTest.unionReceivedSequence([]),
"Passing an empty array should convert the union to a sequence");
assert_true(sequenceTest.unionReceivedSequence([34, 42]),
"Passing an array should convert the union to a sequence");
let obj = createIterable([{done: false, value: 99},
{done: false, value: -3.14},
{done: true}]);
assert_true(sequenceTest.unionReceivedSequence(obj),
"Passing an iterable object should convert the union to a sequence");
}, "Sequences in unions");
test(() => {
let sequenceTest = internals.sequenceTest();
let foods = ["Sushi", "Beer"];
assert_throws_js(TypeError, () => { sequenceTest.identityFoodEnumSequence(foods) },
"Invalid enum type must throw a type error");
foods = createIterable([{done: false, value: "Spaghetti"},
{done: false, value: "Bread"},
{done: true}]);
assert_array_equals(sequenceTest.identityFoodEnumSequence(foods),
["Spaghetti", "Bread"]);
}, "Enum sequences");
test(() => {
let sequenceTest = internals.sequenceTest();
let sequenceCreationFunctions = [
(elem) => { return [elem] },
(elem) => { return createIterable([{done: false, value: elem},
{done: true}]) }
];
for (sequenceCreationFunction of sequenceCreationFunctions) {
let elem = document.createElement('p');
sequenceTest.setElementSequence(sequenceCreationFunction(elem));
assert_array_equals(sequenceTest.getElementSequence(), [elem],
"The same DOM object was stored in the sequence");
assert_not_equals(sequenceTest.getElementSequence()[0],
document.createElement('br'),
"The same DOM object was stored in the sequence");
elem = document.createElement('br');
assert_not_equals(sequenceTest.getElementSequence()[0], elem,
"Changing the original object does not change the sequence value");
}
}, "Converting DOM object sequences");
test(() => {
const sequenceTest = internals.sequenceTest();
const array = [
1,
{valueOf: () => { array.pop(); return 2; }},
3
];
assert_array_equals(
sequenceTest.identityLongSequence(array),
[1, 2],
"Array iteration should respect new length");
}, "Array to sequence<> conversions with pop() during iteration");
test(() => {
const sequenceTest = internals.sequenceTest();
const array = [
1,
{valueOf: () => { array.push(3); return 2; }},
];
assert_array_equals(
sequenceTest.identityLongSequence(array),
[1, 2, 3],
"Array iteration should respect new length");
}, "Array to sequence<> conversions with push() during iteration");
test(() => {
const sequenceTest = internals.sequenceTest();
const array = [
1,
{valueOf: () => { array.length = 3; return 2; }}
];
assert_array_equals(
sequenceTest.identityLongSequence(array),
[1, 2, 0],
"Array iteration should respect new length");
}, "Array to sequence<> conversions with length increase during iteration");
test(() => {
const sequenceTest = internals.sequenceTest();
const array = [
1,
{valueOf: () => { array.length = 2; return 2; }},
3
];
assert_array_equals(
sequenceTest.identityLongSequence(array),
[1, 2],
"Array iteration should respect new length");
}, "Array to sequence<> conversions with length decrease during iteration");
test(() => {
const sequenceTest = internals.sequenceTest();
const elems = [
document.createElement('div'),
document.createElement('div'),
document.createElement('div'),
document.createElement('div'),
];
sequenceTest.setElementSequence(elems);
assert_array_equals(sequenceTest.getElementSequence(), elems,
"Sequence items are properly converted");
}, "Array to sequence<> conversions with homogenous ScriptWrappable types");
test(() => {
const sequenceTest = internals.sequenceTest();
const elem1 = document.createElement('br');
elem1["my_property"] = "foo";
const elems = [
document.createElement('div'),
elem1,
document.createElement('div'),
document.createElement('span'),
];
sequenceTest.setElementSequence(elems);
assert_array_equals(sequenceTest.getElementSequence(), elems,
"Different types dervied from Element are properly converted");
const node = document.createTextNode("node");
assert_throws_js(TypeError, () => { sequenceTest.setElementSequence([...elems, node]) },
"Invalid types cause exceptions");
assert_throws_js(TypeError, () => { sequenceTest.setElementSequence([...elems, 1]) },
"Invalid types cause exceptions");
}, "Array to sequence<> conversions with heterogeneous ScriptWrappable types");
</script>