Skip to content

Commit

Permalink
Follow spec better when converting ArrayBuffer views to keys
Browse files Browse the repository at this point in the history
  • Loading branch information
dumbmatter committed Oct 25, 2023
1 parent 034293e commit 26b6d8c
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 4 deletions.
27 changes: 23 additions & 4 deletions src/lib/valueToKey.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DataError } from "./errors.js";
import { Key } from "./types.js";

// https://w3c.github.io/IndexedDB/#convert-a-value-to-a-input
// https://w3c.github.io/IndexedDB/#convert-value-to-key
const valueToKey = (input: any, seen?: Set<object>): Key | Key[] => {
if (typeof input === "number") {
if (isNaN(input)) {
Expand All @@ -18,14 +18,33 @@ const valueToKey = (input: any, seen?: Set<object>): Key | Key[] => {
return input;
} else if (
input instanceof ArrayBuffer ||
(typeof SharedArrayBuffer !== "undefined" &&
input instanceof SharedArrayBuffer) ||
(typeof ArrayBuffer !== "undefined" &&
ArrayBuffer.isView &&
ArrayBuffer.isView(input))
) {
if (input instanceof ArrayBuffer) {
return new Uint8Array(input).buffer;
let arrayBuffer;
let offset = 0;
let length = 0;
if (
input instanceof ArrayBuffer ||
(typeof SharedArrayBuffer !== "undefined" &&
input instanceof SharedArrayBuffer)
) {
arrayBuffer = input;
length = input.byteLength;
} else {
arrayBuffer = input.buffer;
offset = input.byteOffset;
length = input.byteLength;
}
return new Uint8Array(input.buffer).buffer;

if ((arrayBuffer as any).detached) {
return new ArrayBuffer(0);
}

return arrayBuffer.slice(offset, offset + length);
} else if (Array.isArray(input)) {
if (seen === undefined) {
seen = new Set();
Expand Down
16 changes: 16 additions & 0 deletions src/test/fakeIndexedDB/fakeIndexedDB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -815,4 +815,20 @@ describe("fakeIndexedDB Tests", () => {
};
});
});

it("properly converts ArrayBuffer to key, accounting for byteLength and byteOffset (issue #89)", () => {
const binary = new ArrayBuffer(16);
const dataView = new DataView(binary, 12, 4);
dataView.setUint32(0, 1234567890);

assert.equal(dataView.byteLength, 4);
assert.equal(dataView.byteOffset, 12);
assert.equal(dataView.getUint32(0), 1234567890);

const key = FDBKeyRange.lowerBound(dataView).lower;
assert.equal(key.byteLength, 4);

const dataView2 = new DataView(key);
assert.equal(dataView2.getUint32(0), 1234567890);
});
});

0 comments on commit 26b6d8c

Please sign in to comment.