Open rotu opened 10 months ago
@zandaqo, this seems like a big effort, and I want to know what you think before I start rewriting your whole library!
Yes, typing can probably be improved, but inheriting from the DataView/TypedArray was a deliberate choice. I want to re-use their methods without writing custom logic for binary writing/reading (or keeping an extra hidden DataView/TypedArray around as some other libraries do) and risking performance because of it. ArrayBufferView
is a type abstraction, it cannot be instantiated, only ArrayBuffer can, but we cannot read/write into it without the views.
Check this out! It took me way too long to figure out but I think this is exactly what you wanted.
// `extends null` isn't necessary but I prefer it.
class BareDataView extends null {
static fromBuffer(...args) {
// construct a new object, passing args to the DataView() constructor
// but use this (i.e. the BareDataView class) to set the prototype
return Reflect.construct(DataView, args, this)
}
}
// Select only the properties we actually want to expose
// i.e. those that are part of the ArrayBufferView interface
for (const prop of ['buffer', 'byteLength', 'byteOffset']) {
const descriptor = Object.getOwnPropertyDescriptor(DataView.prototype,prop)
Reflect.defineProperty(BareDataView.prototype, prop, descriptor)
}
// Set up some nicely chosen bytes
let myBytes = new Uint8Array([0xff,0xff,0x00,0x84,0x5f,0xed,0xff,0xff])
let b = BareDataView.fromBuffer(myBytes.buffer)
// it has the buffer property!
console.log('buffer' in b) // true
// it doesn't have other DataView member!
console.log('getUint32' in b) // false
// but we can still use DataView methods
console.log(Reflect.apply(DataView.prototype.getUint32, b, [2])) // 8675309
Most objects in this library inherit from
DataView
orTypedArray
. That means they have a number of methods which don't respect the type abstraction.e.g. since
Uint16View
extendsDataView
, it has asetFloat32
method. Note this also writes outside of the 2 bytes one expects the view to refer to. e.g. sinceGridMixin
extends aTypedArray
, it hasmap
,at
,findIndex
, which all use linear indexing.Furthermore,
Int32View
extendsUint8View
. This renders the type annotationx: Uint8View
practically meaningless.It would be nice if this library used less inheritance. It does make sense for binary-backed objects to implement the more minimal
ArrayBufferView
interface ({buffer, byteLength, byteOffset}
).