refactor(zip): diagnose `.write()` of non-`Uint8Array`
MODIFY
packages/zip/src/buffer-writer.js
packages/zip/src/buffer-writer.js
// @ts-check
/* eslint no-bitwise: ["off"] */
+/**
+ * @type {WeakMap<BufferWriter, {
+ * length: number,
+ * index: number,
+ * bytes: Uint8Array,
+ * data: DataView,
+ * capacity: number,
+ * }>}
+ */
const privateFields = new WeakMap();
+/**
+ * @param {BufferWriter} self
+ */
+const getPrivateFields = self => {
+ const fields = privateFields.get(self);
+ if (!fields) {
+ throw new Error('BufferWriter fields are not initialized');
+ }
+ return fields;
+};
+
+const assertNatNumber = n => {
+ if (Number.isSafeInteger(n) && n >= 0) {
+ return;
+ }
+ throw TypeError(`must be a non-negative integer, got ${n}`);
+};
+
export class BufferWriter {
/**
* @returns {number}
*/
get length() {
- return privateFields.get(this).length;
+ return getPrivateFields(this).length;
}
/**
* @returns {number}
*/
get index() {
- return privateFields.get(this).index;
+ return getPrivateFields(this).index;
}
/**
@@ -44,7 +71,8 @@ export class BufferWriter {
* @param {number} required
*/
ensureCanSeek(required) {
- const fields = privateFields.get(this);
+ assertNatNumber(required);
+ const fields = getPrivateFields(this);
let capacity = fields.capacity;
while (capacity < required) {
capacity *= 2;
@@ -61,7 +89,7 @@ export class BufferWriter {
* @param {number} index
*/
seek(index) {
- const fields = privateFields.get(this);
+ const fields = getPrivateFields(this);
this.ensureCanSeek(index);
fields.index = index;
fields.length = Math.max(fields.index, fields.length);
@@ -71,7 +99,8 @@ export class BufferWriter {
* @param {number} size
*/
ensureCanWrite(size) {
- const fields = privateFields.get(this);
+ assertNatNumber(size);
+ const fields = getPrivateFields(this);
this.ensureCanSeek(fields.index + size);
}
@@ -79,10 +108,10 @@ export class BufferWriter {
* @param {Uint8Array} bytes
*/
write(bytes) {
- const fields = privateFields.get(this);
- this.ensureCanWrite(bytes.length);
+ const fields = getPrivateFields(this);
+ this.ensureCanWrite(bytes.byteLength);
fields.bytes.set(bytes, fields.index);
- fields.index += bytes.length;
+ fields.index += bytes.byteLength;
fields.length = Math.max(fields.index, fields.length);
}
@@ -91,7 +120,9 @@ export class BufferWriter {
* @param {number} end
*/
writeCopy(start, end) {
- const fields = privateFields.get(this);
+ assertNatNumber(start);
+ assertNatNumber(end);
+ const fields = getPrivateFields(this);
const size = end - start;
this.ensureCanWrite(size);
fields.bytes.copyWithin(fields.index, start, end);
@@ -103,7 +134,7 @@ export class BufferWriter {
* @param {number} value
*/
writeUint8(value) {
- const fields = privateFields.get(this);
+ const fields = getPrivateFields(this);
this.ensureCanWrite(1);
fields.data.setUint8(fields.index, value);
fields.index += 1;
@@ -115,7 +146,7 @@ export class BufferWriter {
* @param {boolean=} littleEndian
*/
writeUint16(value, littleEndian) {
- const fields = privateFields.get(this);
+ const fields = getPrivateFields(this);
this.ensureCanWrite(2);
const index = fields.index;
fields.data.setUint16(index, value, littleEndian);
@@ -128,7 +159,7 @@ export class BufferWriter {
* @param {boolean=} littleEndian
*/
writeUint32(value, littleEndian) {
- const fields = privateFields.get(this);
+ const fields = getPrivateFields(this);
this.ensureCanWrite(4);
const index = fields.index;
fields.data.setUint32(index, value, littleEndian);
@@ -142,7 +173,7 @@ export class BufferWriter {
* @returns {Uint8Array}
*/
subarray(begin, end) {
- const fields = privateFields.get(this);
+ const fields = getPrivateFields(this);
return fields.bytes.subarray(0, fields.length).subarray(begin, end);
}

refactor(zip): diagnose `.write()` of non-`Uint8Array`