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.
57 lines
2.1 KiB
57 lines
2.1 KiB
'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); |
|
}, |
|
}));
|
|
|