2023-10-03 11:14:36 +08:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
var wrapIdbValue = require('./wrap-idb-value.cjs');
|
|
|
|
|
|
|
|
const advanceMethodProps = ['continue', 'continuePrimaryKey', 'advance'];
|
|
|
|
const methodMap = {};
|
|
|
|
const advanceResults = new WeakMap();
|
|
|
|
const ittrProxiedCursorToOriginalProxy = new WeakMap();
|
|
|
|
const cursorIteratorTraps = {
|
|
|
|
get(target, prop) {
|
|
|
|
if (!advanceMethodProps.includes(prop))
|
|
|
|
return target[prop];
|
|
|
|
let cachedFunc = methodMap[prop];
|
|
|
|
if (!cachedFunc) {
|
|
|
|
cachedFunc = methodMap[prop] = function (...args) {
|
|
|
|
advanceResults.set(this, ittrProxiedCursorToOriginalProxy.get(this)[prop](...args));
|
|
|
|
};
|
|
|
|
}
|
|
|
|
return cachedFunc;
|
|
|
|
},
|
|
|
|
};
|
|
|
|
async function* iterate(...args) {
|
|
|
|
// tslint:disable-next-line:no-this-assignment
|
|
|
|
let cursor = this;
|
|
|
|
if (!(cursor instanceof IDBCursor)) {
|
|
|
|
cursor = await cursor.openCursor(...args);
|
|
|
|
}
|
|
|
|
if (!cursor)
|
|
|
|
return;
|
|
|
|
cursor = cursor;
|
|
|
|
const proxiedCursor = new Proxy(cursor, cursorIteratorTraps);
|
|
|
|
ittrProxiedCursorToOriginalProxy.set(proxiedCursor, cursor);
|
|
|
|
// Map this double-proxy back to the original, so other cursor methods work.
|
|
|
|
wrapIdbValue.reverseTransformCache.set(proxiedCursor, wrapIdbValue.unwrap(cursor));
|
|
|
|
while (cursor) {
|
|
|
|
yield proxiedCursor;
|
|
|
|
// If one of the advancing methods was not called, call continue().
|
|
|
|
cursor = await (advanceResults.get(proxiedCursor) || cursor.continue());
|
|
|
|
advanceResults.delete(proxiedCursor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function isIteratorProp(target, prop) {
|
|
|
|
return ((prop === Symbol.asyncIterator &&
|
|
|
|
wrapIdbValue.instanceOfAny(target, [IDBIndex, IDBObjectStore, IDBCursor])) ||
|
|
|
|
(prop === 'iterate' && wrapIdbValue.instanceOfAny(target, [IDBIndex, IDBObjectStore])));
|
|
|
|
}
|
|
|
|
wrapIdbValue.replaceTraps((oldTraps) => ({
|
|
|
|
...oldTraps,
|
|
|
|
get(target, prop, receiver) {
|
|
|
|
if (isIteratorProp(target, prop))
|
|
|
|
return iterate;
|
|
|
|
return oldTraps.get(target, prop, receiver);
|
|
|
|
},
|
|
|
|
has(target, prop) {
|
|
|
|
return isIteratorProp(target, prop) || oldTraps.has(target, prop);
|
|
|
|
},
|
|
|
|
}));
|