Last active
May 20, 2024 02:54
-
-
Save inexorabletash/5462871 to your computer and use it in GitHub Desktop.
Helper for creating an IDBKeyRange for all keys with a given prefix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright 2019 Google LLC. | |
// SPDX-License-Identifier: Apache-2.0 | |
// Basic p(r)olyfill for proposed feature | |
// This defines no successor of empty arrays, so the range for prefix | |
// [] or [[],[]] has no upper bound. | |
// An alternate definition would preclude adding additional nesting, | |
// so the range for prefix [] would have upper bound [[]] and the | |
// range for prefix [[], []] would have upper bound [[], [[]]]. | |
IDBKeyRange.forPrefix = function(prefix) { | |
// Ensure prefix is a valid key itself: | |
if (indexedDB.cmp(prefix, prefix) !== 0) throw new TypeError(); | |
var MAX_DATE_VALUE = 8640000000000000; | |
var UPPER_BOUND = { | |
NUMBER: new Date(-MAX_DATE_VALUE), | |
DATE: "", | |
STRING: [], | |
ARRAY: undefined | |
}; | |
var upperKey = successor(prefix); | |
if (upperKey === undefined) | |
return IDBKeyRange.lowerBound(prefix); | |
return IDBKeyRange.bound(prefix, upperKey, false, true); | |
function successor(key) { | |
if (typeof key === 'number') { | |
if (key === Infinity) | |
return UPPER_BOUND.NUMBER; | |
if (key === -Infinity) | |
return -Number.MAX_VALUE; | |
if (key === 0) | |
return Number.MIN_VALUE; | |
var epsilon = Math.abs(key); | |
while (key + epsilon / 2 !== key) | |
epsilon = epsilon / 2; | |
return key + epsilon; | |
} | |
if (key instanceof Date) { | |
if (key.valueOf() + 1 > MAX_DATE_VALUE) | |
return UPPER_BOUND.DATE; | |
return new Date(key.valueOf() + 1); | |
} | |
if (typeof key === 'string') { | |
var len = key.length; | |
while (len > 0) { | |
var head = key.substring(0, len - 1), | |
tail = key.charCodeAt(len - 1); | |
if (tail !== 0xFFFF) | |
return head + String.fromCharCode(tail + 1); | |
key = head; | |
--len; | |
} | |
return UPPER_BOUND.STRING; | |
} | |
if (Array.isArray(key)) { | |
key = key.slice(); // Operate on a copy. | |
len = key.length; | |
while (len > 0) { | |
tail = successor(key.pop()); | |
if (tail !== undefined) { | |
key.push(tail); | |
return key; | |
} | |
--len; | |
} | |
return UPPER_BOUND.ARRAY; | |
} | |
throw new TypeError(); | |
} | |
}; |
@jfroelich, unlike would be the case for let
or const
, the presence of an earlier var len
in the function ensures the declaration gets effectively hoisted to the top, so line 62 is not a problem. It is generally considered better style though to declare such var
s at the top of the function, especially in such cases where it is used out of the defining block like this.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Should line 62 be
var len = key.length
?