add idb api
This commit is contained in:
parent
b777938cab
commit
a645ac4653
4 changed files with 124 additions and 1 deletions
|
|
@ -1,11 +1,35 @@
|
|||
/**
|
||||
*
|
||||
* @template Data
|
||||
* @template Target
|
||||
* @template That
|
||||
* @property {Data} data
|
||||
* @property {Target} target
|
||||
* @property {That} that
|
||||
*/
|
||||
class HookEvent {
|
||||
#intercepted;
|
||||
#returnValue;
|
||||
/**
|
||||
*
|
||||
* @param {Data} data
|
||||
* @param {Target} target
|
||||
* @param {That} that
|
||||
*/
|
||||
constructor(data = {}, target = null, that = null) {
|
||||
this.#intercepted = false;
|
||||
this.#returnValue = null;
|
||||
/**
|
||||
* @type {Data}
|
||||
*/
|
||||
this.data = data;
|
||||
/**
|
||||
* @type {Target}
|
||||
*/
|
||||
this.target = target;
|
||||
/**
|
||||
* @type {That}
|
||||
*/
|
||||
this.that = that;
|
||||
}
|
||||
get intercepted() {
|
||||
|
|
|
|||
62
src/client/idb.js
Normal file
62
src/client/idb.js
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import EventEmitter from 'events';
|
||||
import HookEvent from './hook.js';
|
||||
|
||||
/**
|
||||
* @typedef {import('./index').default} Ultraviolet
|
||||
*/
|
||||
|
||||
class IDBApi extends EventEmitter {
|
||||
/**
|
||||
*
|
||||
* @param {Ultraviolet} ctx
|
||||
*/
|
||||
constructor(ctx) {
|
||||
super();
|
||||
this.ctx = ctx;
|
||||
this.window = this.ctx.window;
|
||||
this.IDBDatabase = this.window.IDBDatabase || {};
|
||||
this.idbDatabaseProto = this.IDBDatabase.prototype || {};
|
||||
this.IDBFactory = this.window.IDBFactory || {};
|
||||
this.idbFactoryProto = this.IDBFactory.prototype || {};
|
||||
this.open = this.idbFactoryProto.open;
|
||||
}
|
||||
overrideOpen() {
|
||||
this.ctx.override(
|
||||
this.IDBFactory.prototype,
|
||||
'open',
|
||||
(target, that, args) => {
|
||||
if (!args.length) return target.apply(that, args);
|
||||
|
||||
if (!args.length) return target.apply(that, args);
|
||||
const [name, version] = args;
|
||||
|
||||
const event = new HookEvent({ name, version }, target, that);
|
||||
this.emit('idbFactoryOpen', event);
|
||||
|
||||
if (event.intercepted) return event.returnValue;
|
||||
return event.target.call(
|
||||
event.that,
|
||||
event.data.name,
|
||||
event.data.version
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
overrideName() {
|
||||
this.ctx.overrideDescriptor(this.idbDatabaseProto, 'name', {
|
||||
get: (target, that) => {
|
||||
const event = new HookEvent(
|
||||
{ value: target.call(that) },
|
||||
target,
|
||||
that
|
||||
);
|
||||
this.emit('idbFactoryName', event);
|
||||
|
||||
if (event.intercepted) return event.returnValue;
|
||||
return event.data.value;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default IDBApi;
|
||||
|
|
@ -16,6 +16,7 @@ import URLApi from './url.js';
|
|||
import EventEmitter from 'events';
|
||||
import StorageApi from './storage.js';
|
||||
import StyleApi from './dom/style.js';
|
||||
import IDBApi from './idb.js';
|
||||
|
||||
class UVClient extends EventEmitter {
|
||||
constructor(window = self, worker = !window.window) {
|
||||
|
|
@ -43,6 +44,7 @@ class UVClient extends EventEmitter {
|
|||
this.worker = worker;
|
||||
this.fetch = new Fetch(this);
|
||||
this.xhr = new Xhr(this);
|
||||
this.idb = new IDBApi(this);
|
||||
this.history = new History(this);
|
||||
this.element = new ElementApi(this);
|
||||
this.node = new NodeApi(this);
|
||||
|
|
@ -67,10 +69,19 @@ class UVClient extends EventEmitter {
|
|||
this.worker
|
||||
);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {*} obj
|
||||
* @param {*} prop
|
||||
* @param {WrapFun} wrapper
|
||||
* @param {*} construct
|
||||
* @returns
|
||||
*/
|
||||
override(obj, prop, wrapper, construct) {
|
||||
// if (!(prop in obj)) return false;
|
||||
const wrapped = this.wrap(obj, prop, wrapper, construct);
|
||||
return (obj[prop] = wrapped);
|
||||
obj[prop] = wrapped;
|
||||
return wrapped;
|
||||
}
|
||||
overrideDescriptor(obj, prop, wrapObj = {}) {
|
||||
const wrapped = this.wrapDescriptor(obj, prop, wrapObj);
|
||||
|
|
@ -78,6 +89,19 @@ class UVClient extends EventEmitter {
|
|||
this.nativeMethods.defineProperty(obj, prop, wrapped);
|
||||
return wrapped;
|
||||
}
|
||||
/**
|
||||
* @template {Function} [T=Function]
|
||||
* @typedef {(fn: T, that: any, args: any[]) => {}} WrapFun
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* @template T
|
||||
* @param {*} obj
|
||||
* @param {*} prop
|
||||
* @param {WrapFun<T>} wrap
|
||||
* @param {boolean} construct
|
||||
* @returns {T}
|
||||
*/
|
||||
wrap(obj, prop, wrap, construct) {
|
||||
const fn = obj[prop];
|
||||
if (!fn) return fn;
|
||||
|
|
|
|||
|
|
@ -409,6 +409,17 @@ function __uvHook(window) {
|
|||
event.data.url = __uv.rewriteUrl(event.data.url);
|
||||
});
|
||||
|
||||
// IDB
|
||||
client.idb.on('idbFactoryOpen', (event) => {
|
||||
event.data.name = `${__uv.meta.url.origin}@${event.data.name}`;
|
||||
});
|
||||
|
||||
client.idb.on('idbFactoryName', (event) => {
|
||||
event.data.value = event.data.value.slice(
|
||||
__uv.meta.url.origin.length + 1 /*the @*/
|
||||
);
|
||||
});
|
||||
|
||||
// History
|
||||
client.history.on('replaceState', (event) => {
|
||||
if (event.data.url)
|
||||
|
|
@ -1400,6 +1411,8 @@ function __uvHook(window) {
|
|||
//client.document.overrideQuerySelector();
|
||||
client.object.overrideGetPropertyNames();
|
||||
client.object.overrideGetOwnPropertyDescriptors();
|
||||
client.idb.overrideName();
|
||||
client.idb.overrideOpen();
|
||||
client.history.overridePushState();
|
||||
client.history.overrideReplaceState();
|
||||
client.eventSource.overrideConstruct();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue