You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
58 lines
2.1 KiB
58 lines
2.1 KiB
2 years ago
|
'use strict';
|
||
|
|
||
|
var wrapIdbValue = require('./wrap-idb-value.js');
|
||
|
|
||
|
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);
|
||
|
},
|
||
|
}));
|