taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 3f2c6a741460e555c5e8faacbad0c22b2d5e4eb7
parent e40233c0378150094e025125960510c24b5bcdef
Author: Florian Dold <dold@taler.net>
Date:   Sun, 19 Jul 2026 22:41:28 +0200

idb-bridge: fix multiEntry indexes never matching

getIndexKeys branched on an array keyPath; a multiEntry index has a string
keyPath with an array value, so each element was never indexed separately.

Diffstat:
Mpackages/idb-bridge/src/util/getIndexKeys.ts | 40+++++++++++++++++++++++++++++++++-------
1 file changed, 33 insertions(+), 7 deletions(-)

diff --git a/packages/idb-bridge/src/util/getIndexKeys.ts b/packages/idb-bridge/src/util/getIndexKeys.ts @@ -24,16 +24,42 @@ export function getIndexKeys( keyPath: IDBKeyPath | IDBKeyPath[], multiEntry: boolean, ): IDBValidKey[] { - if (multiEntry && Array.isArray(keyPath)) { - const keys = []; - for (const subkeyPath of keyPath) { - const key = extractKey(subkeyPath, value); + if (multiEntry && typeof keyPath === "string") { + // A multiEntry index has a *string* keyPath whose value is an array, and + // indexes each element separately. (A multiEntry index with an array + // keyPath is invalid per spec and rejected by createIndex.) Matching on + // Array.isArray(keyPath) instead meant this branch never ran for a real + // multiEntry index: the array value fell through below and was indexed + // as one compound key, so a lookup for a single element matched nothing. + const key = extractKey(keyPath, value); + if (!Array.isArray(key)) { + // Not an array: behaves like an ordinary single-key index. + if (key == null) { + return []; + } + try { + return [valueToKey(key)]; + } catch { + return []; + } + } + const keys: IDBValidKey[] = []; + const seen = new Set<string>(); + for (const item of key) { + let k: IDBValidKey; try { - const k = valueToKey(key); - keys.push(k); + k = valueToKey(item); } catch { - // Ignore invalid subkeys + // Spec: entries that are not valid keys are skipped, not fatal. + continue; + } + // Spec: duplicate entries are recorded once. + const dedupeKey = JSON.stringify(k); + if (seen.has(dedupeKey)) { + continue; } + seen.add(dedupeKey); + keys.push(k); } return keys; } else if (typeof keyPath === "string" || Array.isArray(keyPath)) {