Polyfill `BigInt64Array`/`BigUint64Array` and `DataView.prototype.{get,set}Big{Int,Uint}64`?
mathiasbynens opened this issue ยท 7 comments
Any idea how the API should look like? I'm not sure if adding to the DataView.prototype would be ok.
Anyway I started playing around and implemented DataView.{get/set}BigUint64: https://gist.github.com/graup/815c9ac65c2bac8a56391f0ca23636fc
If this approach makes sense I could continue implementing the rest of the functions.
Thanks for getting started with this!
I think that JSBI should not interfere with a native implementation. Its purpose is to provide the same functionality, but with separate syntax that can easily be transpiled away. So just like the JSBI.BigInt
constructor, the typed arrays should be properties on the JSBI object too: JSBI.BigInt64Array
and JSBI.BigUint64Array
.
DataView is a bit trickier, but I think we should apply the same guidelines there, which means putting static methods onto the JSBI object, even if that means that client code will look quite different: instead of my_dataview.getBigInt64(...)
you'd have JSBI.DataViewGetBigInt64(my_dataview, ...)
or something like that.
Does that make sense?
Note that useNativeBigIntsIfAvailable
has gone away.
Ok, I'll give that a shot.
For the DataView another option could be to use the polyfill functions with call
like JSBI.DataViewGetBigInt64.call(view, ...)
, then the transpile step would just be to replace the function name (JSBI.DataViewGetBigInt64.call(view, ...)
=> DataView.getBigInt64.call(view, ...)
). Do you think that would be worth it? Maybe even JSBI.DataView.getBigInt64.call
? Then when writing code all you have to remember is putting JSBI.
in the front.
IMHO .call
is a little awkward to use. Iโd prefer JSBI.DataViewGetBigInt64(myDataView, โฆ)
โ myDataView.getBigInt64(โฆ)
.
Since Safari supports BigInt
now, here are some polyfills for a few of the remaining missing bits, getBigUint64
/setBigUint64
, which might come in handy for people who stumble upon this.
No guarantees they're correct in all cases, but they at least work partially. Also no implementations for getBigInt64
/setBigInt64
; those might require some extra care to get right.
DataView.prototype.setBigUint64 ??= function(byteOffset, value, littleEndian) {
const wh = Number((value >> 32n) & 0xFFFFFFFFn);
const wl = Number((value ) & 0xFFFFFFFFn);
const [h, l] = littleEndian ? [4, 0] : [0, 4];
this.setUint32(byteOffset + h, wh, littleEndian);
this.setUint32(byteOffset + l, wl, littleEndian);
};
DataView.prototype.getBigUint64 ??= function(byteOffset, littleEndian) {
const [h, l] = littleEndian ? [4, 0] : [0, 4];
const wh = BigInt(this.getUint32(byteOffset + h, littleEndian));
const wl = BigInt(this.getUint32(byteOffset + l, littleEndian));
return (wh << 32n) + wl;
};
DataView operations are now supported (as of v4.2.0, just released).
Polyfilling BigInt64Array
/BigUint64Array
is currently not planned, for the following reasons:
- TypedArrays have a huge API surface, at the same time most of their functions are probably rarely used. So polyfilling them would be a massive effort, and most of that effort would probably be a waste.
- To support indexed accesses (
my_polyfilled_bigint64array[0]
), the polyfill would have to use Proxies, but for the browsers that are relevant today,Proxy
support is not much more widespread than nativeBigInt64Array
support. In particular, all the "evergreen" browsers support both, IE11 supports neither. - Skipping support for indexed accesses and using named methods instead (likely
.get(index)
and.set(index, value)
) would be rather ugly, and more importantly, due to how JavaScript works there would be no way to actually disallow indexed accesses, so they would still work, they just wouldn't do the right thing.
If anyone wants to go to all that trouble, I'd be willing to review a PR, but personally I'm not convinced the effort is worth it, so to reflect that I'm closing this issue.