Source code
Revision control
Copy as Markdown
Other Tools
const types = [
"Int8",
"Int16",
"Int32",
"Uint8",
"Uint16",
"Uint32",
"Float16",
"Float32",
"Float64",
];
function convert(type, value) {
let num = Number(value);
switch (type) {
case "Int8":
return ((num | 0) << 24) >> 24;
case "Int16":
return ((num | 0) << 16) >> 16;
case "Int32":
return (num | 0);
case "Uint8":
return (num >>> 0) & 0xff;
case "Uint16":
return (num >>> 0) & 0xffff;
case "Uint32":
return (num >>> 0);
case "Uint8Clamped": {
if (Number.isNaN(num)) {
return 0;
}
let clamped = Math.max(0, Math.min(num, 255));
let f = Math.floor(clamped);
if (clamped < f + 0.5) {
return f;
}
if (clamped > f + 0.5) {
return f + 1;
}
return f + (f & 1);
}
case "Float16":
return Math.f16round(num);
case "Float32":
return Math.fround(num);
case "Float64":
return num;
}
throw new Error();
}
function runTest(type, initial, values) {
let expected = values.map(v => convert(type, v));
assertEq(
expected.some(e => Object.is(e, initial)),
false,
"initial must be different from the expected values"
);
// Create a fresh function to ensure ICs are specific to a single DataView function.
let test = Function("initial, values, expected", `
let ab = new ArrayBuffer(16);
let dv = new DataView(ab);
for (let i = 0; i < 200; ++i) {
dv.set${type}(0, initial);
dv.set${type}(0, values[i % values.length]);
assertEq(dv.get${type}(0), expected[i % expected.length]);
}
`);
test(initial, values, expected);
}
const tests = [
// |null| is coerced to zero.
{
initial: 1,
values: [null],
},
// |undefined| is coerced to zero or NaN.
{
initial: 1,
values: [undefined],
},
// |false| is coerced to zero and |true| is coerced to one.
{
initial: 2,
values: [false, true],
},
// Strings without a fractional part.
{
initial: 42,
values: [
"0", "1", "10", "111", "128", "256", "0x7fffffff", "0xffffffff",
],
},
// Strings without a fractional part, but a leading minus sign.
{
initial: 42,
values: [
"-0", "-1", "-10", "-111", "-128", "-256", "-2147483647", "-4294967295",
],
},
// Strings with a fractional number part.
{
initial: 42,
values: [
"0.1", "1.2", "10.8", "111.9",
"-0.1", "-1.2", "-10.8", "-111.9",
],
},
// Special values and strings not parseable as a number.
{
initial: 42,
values: ["Infinity", "-Infinity", "NaN", "foobar"],
},
];
for (let type of types) {
for (let {initial, values} of tests) {
runTest(type, initial, values);
}
}