Refactor & speed up styleSectionsEqual
This commit is contained in:
parent
19f1490f0a
commit
d53db2d45c
83
storage.js
83
storage.js
|
@ -367,13 +367,17 @@ function getDomains(url) {
|
|||
|
||||
|
||||
function getType(o) {
|
||||
if (typeof o == "undefined" || typeof o == "string") {
|
||||
if (typeof o == 'undefined' || typeof o == 'string') {
|
||||
return typeof o;
|
||||
}
|
||||
if (o instanceof Array) {
|
||||
return "array";
|
||||
// with the persistent cachedStyles the Array reference is usually different
|
||||
// so let's check for e.g. type of 'every' which is only present on arrays
|
||||
// (in the context of our extension)
|
||||
if (o instanceof Array || typeof o.every == 'function') {
|
||||
return 'array';
|
||||
}
|
||||
throw "Not supported - " + o;
|
||||
console.warn('Unsupported type:', o);
|
||||
return 'undefined';
|
||||
}
|
||||
|
||||
const namespacePattern = /^\s*(@namespace[^;]+;\s*)+$/;
|
||||
|
@ -752,29 +756,56 @@ function styleSectionsEqual(styleA, styleB) {
|
|||
if (styleA.sections.length != styleB.sections.length) {
|
||||
return false;
|
||||
}
|
||||
const properties = ['code', 'urlPrefixes', 'urls', 'domains', 'regexps'];
|
||||
return styleA.sections.every(sectionA =>
|
||||
styleB.sections.some(sectionB =>
|
||||
properties.every(property => sectionEquals(sectionA, sectionB, property))
|
||||
)
|
||||
);
|
||||
|
||||
function sectionEquals(a, b, property) {
|
||||
const aProp = a[property], typeA = getType(aProp);
|
||||
const bProp = b[property], typeB = getType(bProp);
|
||||
if (typeA != typeB) {
|
||||
// consider empty arrays equivalent to lack of property
|
||||
return ((typeA == 'undefined' || (typeA == 'array' && aProp.length == 0)) &&
|
||||
(typeB == 'undefined' || (typeB == 'array' && bProp.length == 0)));
|
||||
const propNames = ['code', 'urlPrefixes', 'urls', 'domains', 'regexps'];
|
||||
const typeBcaches = [];
|
||||
checkingEveryInA: for (let sectionA of styleA.sections) {
|
||||
const typeAcache = new Map();
|
||||
for (let name of propNames) {
|
||||
typeAcache.set(name, getType(sectionA[name]));
|
||||
}
|
||||
if (typeA == 'undefined') {
|
||||
return true;
|
||||
}
|
||||
if (typeA == 'array') {
|
||||
return aProp.length == bProp.length && aProp.every(item => bProp.includes(item));
|
||||
}
|
||||
if (typeA == 'string') {
|
||||
return aProp == bProp;
|
||||
lookingForDupeInB: for (let i = 0, sectionB; (sectionB = styleB.sections[i]); i++) {
|
||||
const typeBcache = typeBcaches[i] = typeBcaches[i] || new Map();
|
||||
comparingProps: for (let name of propNames) {
|
||||
const propA = sectionA[name], typeA = typeAcache.get(name);
|
||||
const propB = sectionB[name];
|
||||
let typeB = typeBcache.get(name);
|
||||
if (!typeB) {
|
||||
typeB = getType(propB);
|
||||
typeBcache.set(name, typeB);
|
||||
}
|
||||
if (typeA != typeB) {
|
||||
const bothEmptyOrUndefined =
|
||||
(typeA == 'undefined' || (typeA == 'array' && propA.length == 0)) &&
|
||||
(typeB == 'undefined' || (typeB == 'array' && propB.length == 0));
|
||||
if (bothEmptyOrUndefined) {
|
||||
continue comparingProps;
|
||||
} else {
|
||||
continue lookingForDupeInB;
|
||||
}
|
||||
}
|
||||
if (typeA == 'undefined') {
|
||||
continue comparingProps;
|
||||
}
|
||||
if (typeA == 'array') {
|
||||
if (propA.length != propB.length) {
|
||||
continue lookingForDupeInB;
|
||||
}
|
||||
for (let item of propA) {
|
||||
if (propB.indexOf(item) < 0) {
|
||||
continue lookingForDupeInB;
|
||||
}
|
||||
}
|
||||
continue comparingProps;
|
||||
}
|
||||
if (typeA == 'string' && propA != propB) {
|
||||
continue lookingForDupeInB;
|
||||
}
|
||||
}
|
||||
// dupe found
|
||||
continue checkingEveryInA;
|
||||
}
|
||||
// dupe not found
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user