smart invalidateCache: try to update filters in-place

This commit is contained in:
tophf 2018-01-11 17:10:14 +03:00
parent 989df35b05
commit bb34538da0
2 changed files with 65 additions and 8 deletions

View File

@ -225,7 +225,14 @@ function filterStyles({
exposeIframes: prefs.get('exposeIframes'),
};
const cacheKey = [enabled, id, matchUrl, md5Url, asHash, strictRegexp].join('\t');
// make sure to use the same order in updateFiltersCache()
const cacheKey =
enabled + '\t' +
id + '\t' +
matchUrl + '\t' +
md5Url + '\t' +
asHash + '\t' +
strictRegexp;
const cached = cachedStyles.filters.get(cacheKey);
let styles;
if (cached) {
@ -541,21 +548,27 @@ function styleCodeEmpty(code) {
function invalidateCache({added, updated, deletedId} = {}) {
if (!cachedStyles.list) {
return;
}
if (!cachedStyles.list) return;
const id = added ? added.id : updated ? updated.id : deletedId;
const cached = cachedStyles.byId.get(id);
if (updated) {
if (cached) {
const reenabled = !cached.enabled && updated.enabled;
const equal = !reenabled && styleSectionsEqual(updated, cached, {ignoreCode: true});
Object.assign(cached, updated);
if (equal) {
updateFiltersCache(cached);
} else {
cachedStyles.filters.clear();
}
cachedStyles.needTransitionPatch.delete(id);
return;
} else {
added = updated;
}
}
if (added) {
if (!cached) {
cachedStyles.list.push(added);
@ -565,22 +578,65 @@ function invalidateCache({added, updated, deletedId} = {}) {
}
return;
}
if (deletedId !== undefined) {
if (cached) {
const cachedIndex = cachedStyles.list.indexOf(cached);
cachedStyles.list.splice(cachedIndex, 1);
cachedStyles.byId.delete(deletedId);
cachedStyles.filters.clear();
for (const {styles} of cachedStyles.filters.values()) {
if (Array.isArray(styles)) {
const index = styles.findIndex(({id}) => id === deletedId);
if (index >= 0) styles.splice(index, 1);
} else if (deletedId in styles) {
delete styles[deletedId];
styles.length--;
}
}
cachedStyles.needTransitionPatch.delete(id);
return;
}
}
cachedStyles.list = null;
cachedStyles.filters.clear();
cachedStyles.needTransitionPatch.clear(id);
}
function updateFiltersCache(style) {
const {id} = style;
for (const [key, {styles}] of cachedStyles.filters.entries()) {
if (Array.isArray(styles)) {
const index = styles.findIndex(style => style.id === id);
if (index >= 0) styles[index] = Object.assign({}, style);
continue;
}
if (id in styles) {
const [, , matchUrl, , , strictRegexp] = key.split('\t');
if (!style.enabled) {
delete styles[id];
continue;
}
const matchUrlBase = matchUrl && matchUrl.includes('#') && matchUrl.split('#', 1)[0];
const sections = getApplicableSections({
style,
matchUrl,
matchUrlBase,
strictRegexp,
skipUrlCheck: true,
});
if (sections.length) {
styles[id] = sections;
} else {
delete styles[id];
styles.length--;
}
}
}
}
function cleanupCachedFilters({force = false} = {}) {
if (!force) {
debounce(cleanupCachedFilters, 1000, {force: true});

View File

@ -1,6 +1,7 @@
'use strict';
function styleSectionsEqual({sections: a}, {sections: b}) {
// ignoreCode=true is used by invalidateCache to determine if cached filters should be cleared
function styleSectionsEqual({sections: a}, {sections: b}, {ignoreCode = false} = {}) {
if (!a || !b) {
return undefined;
}
@ -17,7 +18,7 @@ function styleSectionsEqual({sections: a}, {sections: b}) {
return false;
}
}
return equalOrEmpty(secA.code, secB.code, 'substr', (a, b) => a === b);
return ignoreCode || equalOrEmpty(secA.code, secB.code, 'substr', (a, b) => a === b);
}
function equalOrEmpty(a, b, telltale, comparator) {