mirror of
https://gitlab.com/KevinRoebert/ClearUrls
synced 2025-12-16 06:05:37 +07:00
Pre-compiled Regular Expressions
Previously, regular expressions were compiled inside loops for every URL processed. Now RegExp objects are created once when rules are loaded and stored in the provider instance.
This commit is contained in:
126
clearurls.js
126
clearurls.js
@@ -89,14 +89,14 @@ function removeFieldsFormURL(provider, pureUrl, quiet = false, request = null) {
|
|||||||
/*
|
/*
|
||||||
* Apply raw rules to the URL.
|
* Apply raw rules to the URL.
|
||||||
*/
|
*/
|
||||||
rawRules.forEach(function (rawRule) {
|
rawRules.forEach(function ({ rule: rawRuleStr, regex: rawRuleRegex }) {
|
||||||
let beforeReplace = url;
|
let beforeReplace = url;
|
||||||
url = url.replace(new RegExp(rawRule, "gi"), "");
|
url = url.replace(rawRuleRegex, "");
|
||||||
|
|
||||||
if (beforeReplace !== url) {
|
if (beforeReplace !== url) {
|
||||||
//Log the action
|
//Log the action
|
||||||
if (storage.loggingStatus && !quiet) {
|
if (storage.loggingStatus && !quiet) {
|
||||||
pushToLog(beforeReplace, url, rawRule);
|
pushToLog(beforeReplace, url, rawRuleStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
increaseBadged(quiet, request);
|
increaseBadged(quiet, request);
|
||||||
@@ -113,13 +113,16 @@ function removeFieldsFormURL(provider, pureUrl, quiet = false, request = null) {
|
|||||||
* Only test for matches, if there are fields or fragments that can be cleaned.
|
* Only test for matches, if there are fields or fragments that can be cleaned.
|
||||||
*/
|
*/
|
||||||
if (fields.toString() !== "" || fragments.toString() !== "") {
|
if (fields.toString() !== "" || fragments.toString() !== "") {
|
||||||
rules.forEach(rule => {
|
rules.forEach(({ rule, regex }) => {
|
||||||
const beforeFields = fields.toString();
|
const beforeFields = fields.toString();
|
||||||
const beforeFragments = fragments.toString();
|
const beforeFragments = fragments.toString();
|
||||||
let localChange = false;
|
let localChange = false;
|
||||||
|
|
||||||
|
// Use the pre-compiled regex.
|
||||||
|
// Note: reusing a regex without 'g' flag is safe for .test()
|
||||||
|
|
||||||
for (const field of fields.keys()) {
|
for (const field of fields.keys()) {
|
||||||
if (new RegExp("^"+rule+"$", "gi").test(field)) {
|
if (regex.test(field)) {
|
||||||
fields.delete(field);
|
fields.delete(field);
|
||||||
changes = true;
|
changes = true;
|
||||||
localChange = true;
|
localChange = true;
|
||||||
@@ -127,7 +130,7 @@ function removeFieldsFormURL(provider, pureUrl, quiet = false, request = null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const fragment of fragments.keys()) {
|
for (const fragment of fragments.keys()) {
|
||||||
if (new RegExp("^"+rule+"$", "gi").test(fragment)) {
|
if (regex.test(fragment)) {
|
||||||
fragments.delete(fragment);
|
fragments.delete(fragment);
|
||||||
changes = true;
|
changes = true;
|
||||||
localChange = true;
|
localChange = true;
|
||||||
@@ -360,7 +363,8 @@ function start() {
|
|||||||
let methods = [];
|
let methods = [];
|
||||||
|
|
||||||
if (_completeProvider) {
|
if (_completeProvider) {
|
||||||
enabled_rules[".*"] = true;
|
// enabled_rules[".*"] = true; // Original
|
||||||
|
enabled_rules[".*"] = new RegExp("^.*$", "i");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -402,29 +406,26 @@ function start() {
|
|||||||
* @return {boolean} ProviderURL as RegExp
|
* @return {boolean} ProviderURL as RegExp
|
||||||
*/
|
*/
|
||||||
this.matchURL = function (url) {
|
this.matchURL = function (url) {
|
||||||
|
// Use matchException internal logic
|
||||||
return urlPattern.test(url) && !(this.matchException(url));
|
return urlPattern.test(url) && !(this.matchException(url));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply a rule to a given tuple of rule array.
|
* Helper to update rule maps with compiled regexes.
|
||||||
* @param enabledRuleArray array for enabled rules
|
|
||||||
* @param disabledRulesArray array for disabled rules
|
|
||||||
* @param {String} rule RegExp as string
|
|
||||||
* @param {boolean} isActive Is this rule active?
|
|
||||||
*/
|
*/
|
||||||
this.applyRule = (enabledRuleArray, disabledRulesArray, rule, isActive = true) => {
|
const updateRule = (enabledMap, disabledMap, rule, isActive, compileFn) => {
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
enabledRuleArray[rule] = true;
|
if (!enabledMap[rule]) {
|
||||||
|
try {
|
||||||
if (disabledRulesArray[rule] !== undefined) {
|
enabledMap[rule] = compileFn(rule);
|
||||||
delete disabledRulesArray[rule];
|
} catch (e) {
|
||||||
|
console.error("Invalid regex", rule, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (disabledMap[rule]) delete disabledMap[rule];
|
||||||
} else {
|
} else {
|
||||||
disabledRulesArray[rule] = true;
|
disabledMap[rule] = true;
|
||||||
|
if (enabledMap[rule]) delete enabledMap[rule];
|
||||||
if (enabledRuleArray[rule] !== undefined) {
|
|
||||||
delete enabledRuleArray[rule];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -436,20 +437,22 @@ function start() {
|
|||||||
* @param {boolean} isActive Is this rule active?
|
* @param {boolean} isActive Is this rule active?
|
||||||
*/
|
*/
|
||||||
this.addRule = function (rule, isActive = true) {
|
this.addRule = function (rule, isActive = true) {
|
||||||
this.applyRule(enabled_rules, disabled_rules, rule, isActive);
|
updateRule(enabled_rules, disabled_rules, rule, isActive, r => new RegExp("^" + r + "$", "i"));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return all active rules as an array.
|
* Return all active rules as an array of {rule, regex}.
|
||||||
*
|
*
|
||||||
* @return Array RegExp strings
|
* @return Array Objects
|
||||||
*/
|
*/
|
||||||
this.getRules = function () {
|
this.getRules = function () {
|
||||||
if (!storage.referralMarketing) {
|
let source = enabled_rules;
|
||||||
return Object.keys(Object.assign(enabled_rules, enabled_referralMarketing));
|
if (storage.referralMarketing) {
|
||||||
|
// Determine if we need to merge referral marketing rules
|
||||||
|
// We use a new object to avoid mutating enabled_rules via Object.assign if that was happening
|
||||||
|
source = Object.assign({}, enabled_rules, enabled_referralMarketing);
|
||||||
}
|
}
|
||||||
|
return Object.entries(source).map(([rule, regex]) => ({ rule, regex }));
|
||||||
return Object.keys(enabled_rules);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -460,16 +463,17 @@ function start() {
|
|||||||
* @param {boolean} isActive Is this rule active?
|
* @param {boolean} isActive Is this rule active?
|
||||||
*/
|
*/
|
||||||
this.addRawRule = function (rule, isActive = true) {
|
this.addRawRule = function (rule, isActive = true) {
|
||||||
this.applyRule(enabled_rawRules, disabled_rawRules, rule, isActive);
|
updateRule(enabled_rawRules, disabled_rawRules, rule, isActive, r => new RegExp(r, "gi"));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return all active raw rules as an array.
|
* Return all active raw rules as an array.
|
||||||
*
|
*
|
||||||
* @return Array RegExp strings
|
* @return Array Objects {rule, regex}
|
||||||
*/
|
*/
|
||||||
this.getRawRules = function () {
|
this.getRawRules = function () {
|
||||||
return Object.keys(enabled_rawRules);
|
// return Object.keys(enabled_rawRules);
|
||||||
|
return Object.entries(enabled_rawRules).map(([rule, regex]) => ({ rule, regex }));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -480,7 +484,7 @@ function start() {
|
|||||||
* @param {boolean} isActive Is this rule active?
|
* @param {boolean} isActive Is this rule active?
|
||||||
*/
|
*/
|
||||||
this.addReferralMarketing = function (rule, isActive = true) {
|
this.addReferralMarketing = function (rule, isActive = true) {
|
||||||
this.applyRule(enabled_referralMarketing, disabled_referralMarketing, rule, isActive);
|
updateRule(enabled_referralMarketing, disabled_referralMarketing, rule, isActive, r => new RegExp("^" + r + "$", "i"));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -491,19 +495,7 @@ function start() {
|
|||||||
* @param {Boolean} isActive Is this exception active?
|
* @param {Boolean} isActive Is this exception active?
|
||||||
*/
|
*/
|
||||||
this.addException = function (exception, isActive = true) {
|
this.addException = function (exception, isActive = true) {
|
||||||
if (isActive) {
|
updateRule(enabled_exceptions, disabled_exceptions, exception, isActive, r => new RegExp(r, "i"));
|
||||||
enabled_exceptions[exception] = true;
|
|
||||||
|
|
||||||
if (disabled_exceptions[exception] !== undefined) {
|
|
||||||
delete disabled_exceptions[exception];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
disabled_exceptions[exception] = true;
|
|
||||||
|
|
||||||
if (enabled_exceptions[exception] !== undefined) {
|
|
||||||
delete enabled_exceptions[exception];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -541,11 +533,10 @@ function start() {
|
|||||||
//Add the site blocked alert to every exception
|
//Add the site blocked alert to every exception
|
||||||
if (url === siteBlockedAlert) return true;
|
if (url === siteBlockedAlert) return true;
|
||||||
|
|
||||||
for (const exception in enabled_exceptions) {
|
for (const [exception, regex] of Object.entries(enabled_exceptions)) {
|
||||||
if (result) break;
|
if (result) break;
|
||||||
|
// let exception_regex = new RegExp(exception, "i"); // Old
|
||||||
let exception_regex = new RegExp(exception, "i");
|
result = regex.test(url);
|
||||||
result = exception_regex.test(url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -559,19 +550,7 @@ function start() {
|
|||||||
* @param {Boolean} isActive Is this redirection active?
|
* @param {Boolean} isActive Is this redirection active?
|
||||||
*/
|
*/
|
||||||
this.addRedirection = function (redirection, isActive = true) {
|
this.addRedirection = function (redirection, isActive = true) {
|
||||||
if (isActive) {
|
updateRule(enabled_redirections, disabled_redirections, redirection, isActive, r => new RegExp(r, "i"));
|
||||||
enabled_redirections[redirection] = true;
|
|
||||||
|
|
||||||
if (disabled_redirections[redirection] !== undefined) {
|
|
||||||
delete disabled_redirections[redirection];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
disabled_redirections[redirection] = true;
|
|
||||||
|
|
||||||
if (enabled_redirections[redirection] !== undefined) {
|
|
||||||
delete enabled_redirections[redirection];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -582,11 +561,14 @@ function start() {
|
|||||||
this.getRedirection = function (url) {
|
this.getRedirection = function (url) {
|
||||||
let re = null;
|
let re = null;
|
||||||
|
|
||||||
for (const redirection in enabled_redirections) {
|
for (const [redirection, regex] of Object.entries(enabled_redirections)) {
|
||||||
let result = (url.match(new RegExp(redirection, "i")));
|
// let result = (url.match(new RegExp(redirection, "i"))); // Old
|
||||||
|
let result = url.match(regex);
|
||||||
|
|
||||||
if (result && result.length > 0 && redirection) {
|
if (result && result.length > 0 && redirection) {
|
||||||
re = (new RegExp(redirection, "i")).exec(url)[1];
|
// re = (new RegExp(redirection, "i")).exec(url)[1];
|
||||||
|
// Reuse match result if possible, but exec is same as match for non-g.
|
||||||
|
re = result[1]; // Capture group 1
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -623,7 +605,7 @@ function start() {
|
|||||||
pushToLog(request.url, request.url, translate('log_ping_blocked'));
|
pushToLog(request.url, request.url, translate('log_ping_blocked'));
|
||||||
increaseBadged(false, request);
|
increaseBadged(false, request);
|
||||||
increaseTotalCounter(1);
|
increaseTotalCounter(1);
|
||||||
return {cancel: true};
|
return { cancel: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -642,8 +624,8 @@ function start() {
|
|||||||
if (result.redirect) {
|
if (result.redirect) {
|
||||||
if (providers[i].shouldForceRedirect() &&
|
if (providers[i].shouldForceRedirect() &&
|
||||||
request.type === 'main_frame') {
|
request.type === 'main_frame') {
|
||||||
browser.tabs.update(request.tabId, {url: result.url}).catch(handleError);
|
browser.tabs.update(request.tabId, { url: result.url }).catch(handleError);
|
||||||
return {cancel: true};
|
return { cancel: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -658,9 +640,9 @@ function start() {
|
|||||||
if (result.cancel) {
|
if (result.cancel) {
|
||||||
if (request.type === 'main_frame') {
|
if (request.type === 'main_frame') {
|
||||||
const blockingPage = browser.runtime.getURL("html/siteBlockedAlert.html?source=" + encodeURIComponent(request.url));
|
const blockingPage = browser.runtime.getURL("html/siteBlockedAlert.html?source=" + encodeURIComponent(request.url));
|
||||||
browser.tabs.update(request.tabId, {url: blockingPage}).catch(handleError);
|
browser.tabs.update(request.tabId, { url: blockingPage }).catch(handleError);
|
||||||
|
|
||||||
return {cancel: true};
|
return { cancel: true };
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
redirectUrl: siteBlockedAlert
|
redirectUrl: siteBlockedAlert
|
||||||
@@ -723,7 +705,7 @@ function start() {
|
|||||||
*/
|
*/
|
||||||
browser.webRequest.onBeforeRequest.addListener(
|
browser.webRequest.onBeforeRequest.addListener(
|
||||||
promise,
|
promise,
|
||||||
{urls: ["<all_urls>"], types: getData("types").concat(getData("pingRequestTypes"))},
|
{ urls: ["<all_urls>"], types: getData("types").concat(getData("pingRequestTypes")) },
|
||||||
["blocking"]
|
["blocking"]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user