promisify DB access
This commit is contained in:
parent
02fd4f1abe
commit
acc4d83b9d
|
@ -1,4 +1,4 @@
|
||||||
/* global getDatabase, getStyles, saveStyle */
|
/* global dbExec, getStyles, saveStyle */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// eslint-disable-next-line no-var
|
// eslint-disable-next-line no-var
|
||||||
|
@ -6,7 +6,7 @@ var browserCommands, contextMenus;
|
||||||
|
|
||||||
// *************************************************************************
|
// *************************************************************************
|
||||||
// preload the DB and report errors
|
// preload the DB and report errors
|
||||||
getDatabase(() => {}, (...args) => {
|
dbExec().catch((...args) => {
|
||||||
args.forEach(arg => 'message' in arg && console.error(arg.message));
|
args.forEach(arg => 'message' in arg && console.error(arg.message));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ prefs.subscribe((id, checked) => {
|
||||||
// *************************************************************************
|
// *************************************************************************
|
||||||
|
|
||||||
function webNavigationListener(method, {url, tabId, frameId}) {
|
function webNavigationListener(method, {url, tabId, frameId}) {
|
||||||
getStyles({matchUrl: url, enabled: true, asHash: true}, styles => {
|
getStyles({matchUrl: url, enabled: true, asHash: true}).then(styles => {
|
||||||
if (method && !url.startsWith('chrome:') && tabId >= 0) {
|
if (method && !url.startsWith('chrome:') && tabId >= 0) {
|
||||||
chrome.tabs.sendMessage(tabId, {
|
chrome.tabs.sendMessage(tabId, {
|
||||||
method,
|
method,
|
||||||
|
@ -209,9 +209,9 @@ function updateIcon(tab, styles) {
|
||||||
stylesReceived(styles);
|
stylesReceived(styles);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getTabRealURL(tab).then(url =>
|
getTabRealURL(tab)
|
||||||
getStyles({matchUrl: url, enabled: true, asHash: true},
|
.then(url => getStyles({matchUrl: url, enabled: true, asHash: true}))
|
||||||
stylesReceived));
|
.then(stylesReceived);
|
||||||
|
|
||||||
function stylesReceived(styles) {
|
function stylesReceived(styles) {
|
||||||
let numStyles = styles.length;
|
let numStyles = styles.length;
|
||||||
|
@ -255,7 +255,7 @@ function onRuntimeMessage(request, sender, sendResponse) {
|
||||||
switch (request.method) {
|
switch (request.method) {
|
||||||
|
|
||||||
case 'getStyles':
|
case 'getStyles':
|
||||||
getStyles(request, sendResponse);
|
getStyles(request).then(sendResponse);
|
||||||
return KEEP_CHANNEL_OPEN;
|
return KEEP_CHANNEL_OPEN;
|
||||||
|
|
||||||
case 'saveStyle':
|
case 'saveStyle':
|
||||||
|
@ -263,9 +263,9 @@ function onRuntimeMessage(request, sender, sendResponse) {
|
||||||
return KEEP_CHANNEL_OPEN;
|
return KEEP_CHANNEL_OPEN;
|
||||||
|
|
||||||
case 'healthCheck':
|
case 'healthCheck':
|
||||||
getDatabase(
|
dbExec()
|
||||||
() => sendResponse(true),
|
.then(() => sendResponse(true))
|
||||||
() => sendResponse(false));
|
.catch(() => sendResponse(false));
|
||||||
return KEEP_CHANNEL_OPEN;
|
return KEEP_CHANNEL_OPEN;
|
||||||
|
|
||||||
case 'download':
|
case 'download':
|
||||||
|
|
23
messaging.js
23
messaging.js
|
@ -268,13 +268,13 @@ function sessionStorageHash(name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function onBackgroundReady() {
|
function onBackgroundReady(...dataPassthru) {
|
||||||
return BG ? Promise.resolve() : new Promise(ping);
|
return BG ? Promise.resolve(...dataPassthru) : new Promise(ping);
|
||||||
function ping(resolve) {
|
function ping(resolve) {
|
||||||
chrome.runtime.sendMessage({method: 'healthCheck'}, health => {
|
chrome.runtime.sendMessage({method: 'healthCheck'}, health => {
|
||||||
if (health !== undefined) {
|
if (health !== undefined) {
|
||||||
BG = chrome.extension.getBackgroundPage();
|
BG = chrome.extension.getBackgroundPage();
|
||||||
resolve();
|
resolve(...dataPassthru);
|
||||||
} else {
|
} else {
|
||||||
ping(resolve);
|
ping(resolve);
|
||||||
}
|
}
|
||||||
|
@ -285,20 +285,13 @@ function onBackgroundReady() {
|
||||||
|
|
||||||
// in case Chrome haven't yet loaded the bg page and displays our page like edit/manage
|
// in case Chrome haven't yet loaded the bg page and displays our page like edit/manage
|
||||||
function getStylesSafe(options) {
|
function getStylesSafe(options) {
|
||||||
return new Promise(resolve => {
|
return onBackgroundReady(options).then(BG.getStyles);
|
||||||
if (BG) {
|
|
||||||
BG.getStyles(options, resolve);
|
|
||||||
} else {
|
|
||||||
onBackgroundReady().then(() =>
|
|
||||||
BG.getStyles(options, resolve));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function saveStyleSafe(style) {
|
function saveStyleSafe(style) {
|
||||||
return onBackgroundReady()
|
return onBackgroundReady(BG.deepCopy(style))
|
||||||
.then(() => BG.saveStyle(BG.deepCopy(style)))
|
.then(BG.saveStyle)
|
||||||
.then(savedStyle => {
|
.then(savedStyle => {
|
||||||
if (style.notify === false) {
|
if (style.notify === false) {
|
||||||
handleUpdate(savedStyle, style);
|
handleUpdate(savedStyle, style);
|
||||||
|
@ -309,8 +302,8 @@ function saveStyleSafe(style) {
|
||||||
|
|
||||||
|
|
||||||
function deleteStyleSafe({id, notify = true} = {}) {
|
function deleteStyleSafe({id, notify = true} = {}) {
|
||||||
return onBackgroundReady()
|
return onBackgroundReady({id, notify})
|
||||||
.then(() => BG.deleteStyle({id, notify}))
|
.then(BG.deleteStyle)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (!notify) {
|
if (!notify) {
|
||||||
handleDelete(id);
|
handleDelete(id);
|
||||||
|
|
236
storage.js
236
storage.js
|
@ -43,58 +43,69 @@ var chromeLocal = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function getDatabase(ready, error) {
|
function dbExec(method, data) {
|
||||||
const dbOpenRequest = window.indexedDB.open('stylish', 2);
|
return new Promise((resolve, reject) => {
|
||||||
dbOpenRequest.onsuccess = event => {
|
Object.assign(indexedDB.open('stylish', 2), {
|
||||||
ready(event.target.result);
|
onsuccess(event) {
|
||||||
};
|
const database = event.target.result;
|
||||||
dbOpenRequest.onerror = event => {
|
if (!method) {
|
||||||
console.warn(event.target.errorCode);
|
resolve(database);
|
||||||
if (error) {
|
} else {
|
||||||
error(event);
|
const transaction = database.transaction(['styles'], 'readwrite');
|
||||||
}
|
const store = transaction.objectStore('styles');
|
||||||
};
|
Object.assign(store[method](data), {
|
||||||
dbOpenRequest.onupgradeneeded = event => {
|
onsuccess: event => resolve(event, store, transaction, database),
|
||||||
if (event.oldVersion == 0) {
|
onerror: reject,
|
||||||
event.target.result.createObjectStore('styles', {
|
});
|
||||||
keyPath: 'id',
|
}
|
||||||
autoIncrement: true,
|
},
|
||||||
});
|
onerror(event) {
|
||||||
}
|
console.warn(event.target.errorCode);
|
||||||
};
|
reject(event);
|
||||||
|
},
|
||||||
|
onupgradeneeded(event) {
|
||||||
|
if (event.oldVersion == 0) {
|
||||||
|
event.target.result.createObjectStore('styles', {
|
||||||
|
keyPath: 'id',
|
||||||
|
autoIncrement: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getStyles(options, callback) {
|
function getStyles(options) {
|
||||||
if (cachedStyles.list) {
|
if (cachedStyles.list) {
|
||||||
callback(filterStyles(options));
|
return Promise.resolve(filterStyles(options));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (cachedStyles.mutex.inProgress) {
|
if (cachedStyles.mutex.inProgress) {
|
||||||
cachedStyles.mutex.onDone.push({options, callback});
|
return new Promise(resolve => {
|
||||||
return;
|
cachedStyles.mutex.onDone.push({options, resolve});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
cachedStyles.mutex.inProgress = true;
|
cachedStyles.mutex.inProgress = true;
|
||||||
|
|
||||||
getDatabase(db => {
|
return dbExec('getAll').then(event => {
|
||||||
const tx = db.transaction(['styles'], 'readonly');
|
cachedStyles.list = event.target.result || [];
|
||||||
const os = tx.objectStore('styles');
|
cachedStyles.byId.clear();
|
||||||
os.getAll().onsuccess = event => {
|
const t0 = performance.now();
|
||||||
cachedStyles.list = event.target.result || [];
|
let hasTimeToCompile = true;
|
||||||
cachedStyles.byId.clear();
|
for (const style of cachedStyles.list) {
|
||||||
for (const style of cachedStyles.list) {
|
cachedStyles.byId.set(style.id, style);
|
||||||
cachedStyles.byId.set(style.id, style);
|
if (hasTimeToCompile) {
|
||||||
compileStyleRegExps({style});
|
hasTimeToCompile = !compileStyleRegExps({style}) || performance.now() - t0 > 100;
|
||||||
}
|
}
|
||||||
callback(filterStyles(options));
|
}
|
||||||
|
|
||||||
cachedStyles.mutex.inProgress = false;
|
cachedStyles.mutex.inProgress = false;
|
||||||
for (const {options, callback} of cachedStyles.mutex.onDone) {
|
for (const {options, resolve} of cachedStyles.mutex.onDone) {
|
||||||
callback(filterStyles(options));
|
resolve(filterStyles(options));
|
||||||
}
|
}
|
||||||
cachedStyles.mutex.onDone = [];
|
cachedStyles.mutex.onDone = [];
|
||||||
};
|
return filterStyles(options);
|
||||||
}, null);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -213,83 +224,81 @@ function filterStylesInternal({
|
||||||
|
|
||||||
|
|
||||||
function saveStyle(style) {
|
function saveStyle(style) {
|
||||||
return new Promise(resolve => {
|
const id = Number(style.id) >= 0 ? Number(style.id) : null;
|
||||||
getDatabase(db => {
|
const reason = style.reason;
|
||||||
const tx = db.transaction(['styles'], 'readwrite');
|
const notify = style.notify !== false;
|
||||||
const os = tx.objectStore('styles');
|
delete style.method;
|
||||||
|
delete style.reason;
|
||||||
const id = style.id == '0' ? 0 : Number(style.id) || null;
|
delete style.notify;
|
||||||
const reason = style.reason;
|
if (!style.name) {
|
||||||
const notify = style.notify !== false;
|
delete style.name;
|
||||||
delete style.method;
|
}
|
||||||
delete style.reason;
|
let existed, codeIsUpdated;
|
||||||
delete style.notify;
|
if (id !== null) {
|
||||||
if (!style.name) {
|
// Update or create
|
||||||
delete style.name;
|
style.id = id;
|
||||||
}
|
return dbExec('get', id).then((event, store) => {
|
||||||
let existed, codeIsUpdated;
|
const oldStyle = event.target.result;
|
||||||
|
existed = Boolean(oldStyle);
|
||||||
if (id !== null) {
|
codeIsUpdated = !existed || style.sections && !styleSectionsEqual(style, oldStyle);
|
||||||
// Update or create
|
style = Object.assign({}, oldStyle, style);
|
||||||
style.id = id;
|
return write(style, store);
|
||||||
os.get(id).onsuccess = eventGet => {
|
|
||||||
const oldStyle = eventGet.target.result;
|
|
||||||
existed = Boolean(oldStyle);
|
|
||||||
codeIsUpdated = !existed || style.sections && !styleSectionsEqual(style, oldStyle);
|
|
||||||
write(Object.assign({}, oldStyle, style));
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// Create
|
|
||||||
delete style.id;
|
|
||||||
write(Object.assign({
|
|
||||||
// Set optional things if they're undefined
|
|
||||||
enabled: true,
|
|
||||||
updateUrl: null,
|
|
||||||
md5Url: null,
|
|
||||||
url: null,
|
|
||||||
originalMd5: null,
|
|
||||||
}, style));
|
|
||||||
}
|
|
||||||
|
|
||||||
function write(style) {
|
|
||||||
style.sections = normalizeStyleSections(style);
|
|
||||||
os.put(style).onsuccess = event => {
|
|
||||||
style.id = style.id || event.target.result;
|
|
||||||
invalidateCache(existed ? {updated: style} : {added: style});
|
|
||||||
compileStyleRegExps({style});
|
|
||||||
if (notify) {
|
|
||||||
notifyAllTabs({
|
|
||||||
method: existed ? 'styleUpdated' : 'styleAdded',
|
|
||||||
style, codeIsUpdated, reason,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (reason == 'update') {
|
|
||||||
updateStyleDigest(style);
|
|
||||||
} else if (reason == 'import') {
|
|
||||||
chrome.storage.local.remove(DIGEST_KEY_PREFIX + style.id, ignoreChromeError);
|
|
||||||
}
|
|
||||||
resolve(style);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
} else {
|
||||||
|
// Create
|
||||||
|
delete style.id;
|
||||||
|
style = Object.assign({
|
||||||
|
// Set optional things if they're undefined
|
||||||
|
enabled: true,
|
||||||
|
updateUrl: null,
|
||||||
|
md5Url: null,
|
||||||
|
url: null,
|
||||||
|
originalMd5: null,
|
||||||
|
}, style);
|
||||||
|
return write(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
function write(style, store) {
|
||||||
|
style.sections = normalizeStyleSections(style);
|
||||||
|
if (store) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
store.put(style).onsuccess = event => resolve(done(event));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return dbExec('put', style).then(done);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function done(event) {
|
||||||
|
style.id = style.id || event.target.result;
|
||||||
|
invalidateCache(existed ? {updated: style} : {added: style});
|
||||||
|
compileStyleRegExps({style});
|
||||||
|
if (notify) {
|
||||||
|
notifyAllTabs({
|
||||||
|
method: existed ? 'styleUpdated' : 'styleAdded',
|
||||||
|
style, codeIsUpdated, reason,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (reason == 'update') {
|
||||||
|
updateStyleDigest(style);
|
||||||
|
} else if (reason == 'import') {
|
||||||
|
chrome.storage.local.remove(DIGEST_KEY_PREFIX + style.id, ignoreChromeError);
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function deleteStyle({id, notify = true}) {
|
function deleteStyle({id, notify = true}) {
|
||||||
|
id = Number(id);
|
||||||
chrome.storage.local.remove(DIGEST_KEY_PREFIX + id, ignoreChromeError);
|
chrome.storage.local.remove(DIGEST_KEY_PREFIX + id, ignoreChromeError);
|
||||||
return new Promise(resolve =>
|
return dbExec('delete', id).then(() => {
|
||||||
getDatabase(db => {
|
invalidateCache({deletedId: id});
|
||||||
const tx = db.transaction(['styles'], 'readwrite');
|
if (notify) {
|
||||||
const os = tx.objectStore('styles');
|
notifyAllTabs({method: 'styleDeleted', id});
|
||||||
os.delete(Number(id)).onsuccess = () => {
|
}
|
||||||
invalidateCache({deletedId: id});
|
return id;
|
||||||
if (notify) {
|
});
|
||||||
notifyAllTabs({method: 'styleDeleted', id});
|
|
||||||
}
|
|
||||||
resolve(id);
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -448,11 +457,12 @@ function compileStyleRegExps({style, compileAll}) {
|
||||||
const rx = tryRegExp(anchored);
|
const rx = tryRegExp(anchored);
|
||||||
cachedStyles.regexps.set(cacheKey, rx || false);
|
cachedStyles.regexps.set(cacheKey, rx || false);
|
||||||
if (!compileAll && performance.now() - t0 > 100) {
|
if (!compileAll && performance.now() - t0 > 100) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
19
update.js
19
update.js
|
@ -22,17 +22,14 @@ var updater = {
|
||||||
|
|
||||||
checkAllStyles({observer = () => {}, save = true, ignoreDigest} = {}) {
|
checkAllStyles({observer = () => {}, save = true, ignoreDigest} = {}) {
|
||||||
updater.resetInterval();
|
updater.resetInterval();
|
||||||
return new Promise(resolve => {
|
return getStyles({}).then(styles => {
|
||||||
getStyles({}, styles => {
|
styles = styles.filter(style => style.updateUrl);
|
||||||
styles = styles.filter(style => style.updateUrl);
|
observer(updater.COUNT, styles.length);
|
||||||
observer(updater.COUNT, styles.length);
|
return Promise.all(
|
||||||
Promise.all(styles.map(style =>
|
styles.map(style =>
|
||||||
updater.checkStyle({style, observer, save, ignoreDigest})
|
updater.checkStyle({style, observer, save, ignoreDigest})));
|
||||||
)).then(() => {
|
}).then(() => {
|
||||||
observer(updater.DONE);
|
observer(updater.DONE);
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user