-
Notifications
You must be signed in to change notification settings - Fork 205
Description
QuickJS has an unexpected behavior (at least when compared with other JS engines), where it throws when a typed array is attempting to be set at a index that is out of bounds:
'use strict';
const a = new Uint8Array(1);
console.log(a[0] = 1);
console.log(a[1] = 2);
console.log(a);
$ qjs o.mjs
1
TypeError: out-of-bound numeric index
at <anonymous> (o.mjs:4:20)
Compared to other runtimes:
$ node o.mjs
1
2
Uint8Array(1) [ 1 ]
$ bun o.mjs
1
2
Uint8Array(1) [ 1 ]
$ deno run o.mjs
1
2
Uint8Array(1) [ 1 ]
I believe the relevant part of the spec is here: TypedArraySetElement
It's not super clear to be if this is technically incorrect behavior or not (that is, I see that the function may result in a throw completion, but I don't see where that would happen based on the steps described).
I also found this 10 year old mailing list thread which seems relevant (but never seemed to reach a conclusion): https://esdiscuss.org/topic/should-assigning-to-out-of-bounds-elements-of-a-typed-array-throw-in-strict-mode-code
In practice, this is making the __toBinary()
function defined by esbuild throw this out of bounds error in certain cases,
For reference:
var __toBinary = /* @__PURE__ */ (() => {
var table = new Uint8Array(128);
for (var i = 0; i < 64; i++)
table[i < 26 ? i + 65 : i < 52 ? i + 71 : i < 62 ? i - 4 : i * 4 - 205] = i;
return (base64) => {
var n = base64.length, bytes = new Uint8Array((n - (base64[n - 1] == "=") - (base64[n - 2] == "=")) * 3 / 4 | 0);
for (var i2 = 0, j = 0; i2 < n; ) {
var c0 = table[base64.charCodeAt(i2++)], c1 = table[base64.charCodeAt(i2++)];
var c2 = table[base64.charCodeAt(i2++)], c3 = table[base64.charCodeAt(i2++)];
bytes[j++] = c0 << 2 | c1 >> 4;
bytes[j++] = c1 << 4 | c2 >> 2;
bytes[j++] = c2 << 6 | c3;
}
return bytes;
};
})();
My vote would be to remove this behavior from QuickJS and make the behavior match other JS engines.