diff --git a/src/helpers/adjust-set-utils.js b/src/helpers/adjust-set-utils.js index b804e5ae..791b7b1e 100644 --- a/src/helpers/adjust-set-utils.js +++ b/src/helpers/adjust-set-utils.js @@ -1,7 +1,6 @@ import { nativeIsNaN, nativeIsFinite } from './number-utils'; -import { getWildcardSymbol } from './constants'; -export const shouldMatchAnyDelay = (delay) => delay === getWildcardSymbol(); +export const shouldMatchAnyDelay = (delay) => delay === '*'; /** * Handles input delay value diff --git a/src/helpers/constants.js b/src/helpers/constants.js deleted file mode 100644 index 3aeedfcd..00000000 --- a/src/helpers/constants.js +++ /dev/null @@ -1,5 +0,0 @@ -/** - * Returns wildcard symbol - * @returns {string} '*' - */ -export const getWildcardSymbol = () => '*'; diff --git a/src/helpers/converter.js b/src/helpers/converter.js index 8202edfe..9f5318a9 100644 --- a/src/helpers/converter.js +++ b/src/helpers/converter.js @@ -9,8 +9,6 @@ import { import { isExisting } from './array-utils'; -import { getWildcardSymbol } from './constants'; - import validator from './validator'; import { parseRule } from './parse-rule'; @@ -48,7 +46,7 @@ const UBO_SET_CONSTANT_EMPTY_STRING = '\'\''; const ADG_PREVENT_FETCH_NAME = 'prevent-fetch'; const ADG_PREVENT_FETCH_EMPTY_STRING = ''; -const ADG_PREVENT_FETCH_WILDCARD = getWildcardSymbol(); +const ADG_PREVENT_FETCH_WILDCARD = '*'; const UBO_NO_FETCH_IF_WILDCARD = '/^/'; const ESCAPED_COMMA_SEPARATOR = '\\,'; diff --git a/src/helpers/cookie-utils.js b/src/helpers/cookie-utils.js index a7532cab..332d5896 100644 --- a/src/helpers/cookie-utils.js +++ b/src/helpers/cookie-utils.js @@ -1,4 +1,9 @@ import { nativeIsNaN } from './number-utils'; +import { logMessage } from './log-message'; + +/** + * @typedef { import('../scriptlets/index').Source } Source + */ /** * Checks whether the input path is supported @@ -30,16 +35,16 @@ export const getCookiePath = (rawPath) => { /** * Combines input cookie name, value, and path into string. * + * @param {Source} source * @param {string} rawName * @param {string} rawValue * @param {string} rawPath * * @returns {string} string OR `null` if path is not supported */ -export const concatCookieNameValuePath = (rawName, rawValue, rawPath) => { - const log = console.log.bind(console); // eslint-disable-line no-console +export const concatCookieNameValuePath = (source, rawName, rawValue, rawPath) => { if (!isValidCookieRawPath(rawPath)) { - log(`Invalid cookie path: '${rawPath}'`); + logMessage(source, `Invalid cookie path: '${rawPath}'`); return null; } // eslint-disable-next-line max-len @@ -49,15 +54,16 @@ export const concatCookieNameValuePath = (rawName, rawValue, rawPath) => { /** * Gets supported cookie value * + * @param {Source} source * @param {string} value input cookie value * * @returns {string|null} valid cookie string if ok OR null if not */ -export const getLimitedCookieValue = (value) => { +export const getLimitedCookieValue = (source, value) => { if (!value) { return null; } - const log = console.log.bind(console); // eslint-disable-line no-console + let validValue; if (value === 'true') { validValue = 'true'; @@ -82,11 +88,11 @@ export const getLimitedCookieValue = (value) => { } else if (/^\d+$/.test(value)) { validValue = parseFloat(value); if (nativeIsNaN(validValue)) { - log(`Invalid cookie value: '${value}'`); + logMessage(source, `Invalid cookie value: '${value}'`); return null; } if (Math.abs(validValue) < 0 || Math.abs(validValue) > 15) { - log(`Invalid cookie value: '${value}'`); + logMessage(source, `Invalid cookie value: '${value}'`); return null; } } else { diff --git a/src/helpers/get-wildcard-property-in-chain.js b/src/helpers/get-wildcard-property-in-chain.js index 3f3b1876..0274983b 100644 --- a/src/helpers/get-wildcard-property-in-chain.js +++ b/src/helpers/get-wildcard-property-in-chain.js @@ -1,5 +1,3 @@ -import { getWildcardSymbol } from './constants'; - /** * @typedef Chain * @property {Object} base @@ -23,7 +21,7 @@ export function getWildcardPropertyInChain(base, chain, lookThrough = false, out const pos = chain.indexOf('.'); if (pos === -1) { // for paths like 'a.b.*' every final nested prop should be processed - if (chain === getWildcardSymbol() || chain === '[]') { + if (chain === '*' || chain === '[]') { // eslint-disable-next-line no-restricted-syntax for (const key in base) { // to process each key in base except inherited ones @@ -41,7 +39,7 @@ export function getWildcardPropertyInChain(base, chain, lookThrough = false, out const prop = chain.slice(0, pos); const shouldLookThrough = (prop === '[]' && Array.isArray(base)) - || (prop === getWildcardSymbol() && base instanceof Object); + || (prop === '*' && base instanceof Object); if (shouldLookThrough) { const nextProp = chain.slice(pos + 1); diff --git a/src/helpers/index.js b/src/helpers/index.js index 62cd8fb1..4b17fbd0 100644 --- a/src/helpers/index.js +++ b/src/helpers/index.js @@ -1,32 +1,33 @@ /** * This file must export all used dependencies */ -export * from './constants'; -export * from './random-id'; -export * from './set-property-access'; -export * from './get-property-in-chain'; -export * from './get-wildcard-property-in-chain'; -export * from './string-utils'; -export * from './create-on-error-handler'; -export * from './noop'; -export * from './hit'; -export * from './observer'; -export * from './match-stack'; -export * from './script-source-utils'; -export * from './open-shadow-dom-utils'; + +export * from './add-event-listener-utils'; +export * from './adjust-set-utils'; export * from './array-utils'; export * from './cookie-utils'; +export * from './noop-utils'; export * from './number-utils'; -export * from './adjust-set-utils'; -export * from './request-utils'; export * from './object-utils'; -export * from './prevent-window-open-utils'; -export * from './add-event-listener-utils'; +export * from './script-source-utils'; +export * from './open-shadow-dom-utils'; export * from './prevent-utils'; +export * from './prevent-window-open-utils'; export * from './regexp-utils'; -export * from './random-response'; +export * from './request-utils'; +export * from './storage-utils'; +export * from './string-utils'; + +export * from './log-message'; +export * from './create-on-error-handler'; export * from './get-descriptor-addon'; -export * from './parse-flags'; +export * from './get-property-in-chain'; +export * from './get-wildcard-property-in-chain'; +export * from './hit'; export * from './match-request-props'; -export * from './storage-utils'; +export * from './match-stack'; +export * from './observer'; +export * from './parse-flags'; export * from './parse-keyword-value'; +export * from './random-id'; +export * from './throttle'; diff --git a/src/helpers/log-message.js b/src/helpers/log-message.js new file mode 100644 index 00000000..59504576 --- /dev/null +++ b/src/helpers/log-message.js @@ -0,0 +1,19 @@ +/** + * @typedef { import('../scriptlets/index').Source } Source + */ + +/** + * Conditionally logs message to console. + * Convention is to log messages by source.verbose if such log + * is not a part of scriptlet's functionality, eg on invalid input, + * and use 'forced' argument otherwise. + * @param {Source} source required + * @param {string} message required, message to log + * @param {boolean} [forced=false] to log message unconditionally + */ +export const logMessage = (source, message, forced = false) => { + if (forced || source.verbose) { + // eslint-disable-next-line no-console + console.log(`${source.name}: ${message}`); + } +}; diff --git a/src/helpers/match-request-props.js b/src/helpers/match-request-props.js index 1d292550..63744dde 100644 --- a/src/helpers/match-request-props.js +++ b/src/helpers/match-request-props.js @@ -3,16 +3,22 @@ import { validateParsedData, parseMatchProps, } from './request-utils'; +import { logMessage } from './log-message'; + +/** + * @typedef { import('../scriptlets/index').Source } Source + */ /** * Checks if given propsToMatch string matches with given request data * This is used by prevent-xhr, prevent-fetch, trusted-replace-xhr-response * and trusted-replace-fetch-response scriptlets + * @param {Source} source * @param {string} propsToMatch * @param {Object} requestData object with standard properties of fetch/xhr like url, method etc * @returns {boolean} */ -export const matchRequestProps = (propsToMatch, requestData) => { +export const matchRequestProps = (source, propsToMatch, requestData) => { if (propsToMatch === '' || propsToMatch === '*') { return true; } @@ -21,8 +27,7 @@ export const matchRequestProps = (propsToMatch, requestData) => { const parsedData = parseMatchProps(propsToMatch); if (!validateParsedData(parsedData)) { - // eslint-disable-next-line no-console - console.log(`Invalid parameter: ${propsToMatch}`); + logMessage(source, `Invalid parameter: ${propsToMatch}`); isMatched = false; } else { const matchData = getMatchPropsData(parsedData); diff --git a/src/helpers/noop.js b/src/helpers/noop-utils.js similarity index 100% rename from src/helpers/noop.js rename to src/helpers/noop-utils.js diff --git a/src/helpers/number-utils.js b/src/helpers/number-utils.js index 97fb8213..72b50db7 100644 --- a/src/helpers/number-utils.js +++ b/src/helpers/number-utils.js @@ -34,3 +34,16 @@ export const getNumberFromString = (rawString) => { : parsedDelay; return validDelay; }; + +/** + * Generate a random integer between two values, inclusive + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#getting_a_random_integer_between_two_values_inclusive + * @param {number} min + * @param {number} max + * @returns {number} + */ +export function getRandomIntInclusive(min, max) { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min + 1) + min); +} diff --git a/src/helpers/object-utils.js b/src/helpers/object-utils.js index 1b1fff62..847afe3a 100644 --- a/src/helpers/object-utils.js +++ b/src/helpers/object-utils.js @@ -50,3 +50,19 @@ export const safeGetDescriptor = (obj, prop) => { } return null; }; + +/** + * Set getter and setter to property if it's configurable + * @param {Object} object target object with property + * @param {string} property property name + * @param {PropertyDescriptor} descriptor contains getter and setter functions + * @returns {boolean} is operation successful + */ +export function setPropertyAccess(object, property, descriptor) { + const currentDescriptor = Object.getOwnPropertyDescriptor(object, property); + if (currentDescriptor && !currentDescriptor.configurable) { + return false; + } + Object.defineProperty(object, property, descriptor); + return true; +} diff --git a/src/helpers/observer.js b/src/helpers/observer.js index 63f4ada2..a8f4d129 100644 --- a/src/helpers/observer.js +++ b/src/helpers/observer.js @@ -1,36 +1,11 @@ +import { throttle } from './throttle'; + /** * DOM tree changes observer. Used for 'remove-attr' and 'remove-class' scriptlets * @param {Function} callback - * @param {Boolean} observeAttrs - optional parameter - should observer check attributes changes + * @param {boolean} observeAttrs - optional parameter - should observer check attributes changes */ export const observeDOMChanges = (callback, observeAttrs = false, attrsToObserve = []) => { - /** - * Returns a wrapper, passing the call to 'method' at maximum once per 'delay' milliseconds. - * Those calls that fall into the "cooldown" period, are ignored - * @param {Function} method - * @param {Number} delay - milliseconds - */ - const throttle = (method, delay) => { - let wait = false; - let savedArgs; - const wrapper = (...args) => { - if (wait) { - savedArgs = args; - return; - } - method(...args); - wait = true; - setTimeout(() => { - wait = false; - if (savedArgs) { - wrapper(savedArgs); - savedArgs = null; - } - }, delay); - }; - return wrapper; - }; - /** * 'delay' in milliseconds for 'throttle' method */ diff --git a/src/helpers/prevent-window-open-utils.js b/src/helpers/prevent-window-open-utils.js index b39e4922..73694f86 100644 --- a/src/helpers/prevent-window-open-utils.js +++ b/src/helpers/prevent-window-open-utils.js @@ -1,7 +1,7 @@ import { noopFunc, trueFunc, -} from './noop'; +} from './noop-utils'; import { startsWith, endsWith, diff --git a/src/helpers/random-response.js b/src/helpers/random-response.js deleted file mode 100644 index b38698dd..00000000 --- a/src/helpers/random-response.js +++ /dev/null @@ -1,74 +0,0 @@ -import { getNumberFromString, nativeIsFinite } from './number-utils'; - -/** - * Generate a random integer between two values, inclusive - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#getting_a_random_integer_between_two_values_inclusive - * @param {number} min - * @param {number} max - * @returns {number} - */ -export function getRandomIntInclusive(min, max) { - min = Math.ceil(min); - max = Math.floor(max); - return Math.floor(Math.random() * (max - min + 1) + min); -} - -/** - * Generate a random string, a length of the string is provided as an argument - * @param {number} length - * @returns {string} - */ -export function getRandomStrByLength(length) { - let result = ''; - const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+=~'; - const charactersLength = characters.length; - for (let i = 0; i < length; i += 1) { - result += characters.charAt(Math.floor(Math.random() * charactersLength)); - } - return result; -} - -/** - * Generate a random string - * @param {string} customResponseText - * @returns {string|null} random string or null if passed argument is invalid - */ -export function generateRandomResponse(customResponseText) { - let customResponse = customResponseText; - - if (customResponse === 'true') { - // Generate random alphanumeric string of 10 symbols - customResponse = Math.random().toString(36).slice(-10); - return customResponse; - } - - customResponse = customResponse.replace('length:', ''); - const rangeRegex = /^\d+-\d+$/; - // Return empty string if range is invalid - if (!rangeRegex.test(customResponse)) { - return null; - } - - let rangeMin = getNumberFromString(customResponse.split('-')[0]); - let rangeMax = getNumberFromString(customResponse.split('-')[1]); - - if (!nativeIsFinite(rangeMin) || !nativeIsFinite(rangeMax)) { - return null; - } - - // If rangeMin > rangeMax, swap variables - if (rangeMin > rangeMax) { - const temp = rangeMin; - rangeMin = rangeMax; - rangeMax = temp; - } - - const LENGTH_RANGE_LIMIT = 500 * 1000; - if (rangeMax > LENGTH_RANGE_LIMIT) { - return null; - } - - const length = getRandomIntInclusive(rangeMin, rangeMax); - customResponse = getRandomStrByLength(length); - return customResponse; -} diff --git a/src/helpers/request-utils.js b/src/helpers/request-utils.js index bc93ee3c..044a696c 100644 --- a/src/helpers/request-utils.js +++ b/src/helpers/request-utils.js @@ -1,25 +1,35 @@ import { toRegExp, isValidStrPattern } from './string-utils'; import { getObjectFromEntries } from './object-utils'; +/** + * Returns array of request props that are supported by fetch/xhr scriptlets. + * Includes common 'url' and 'method' props and all other fetch-specific props + * @returns {string[]} + */ +const getRequestProps = () => [ + 'url', + 'method', + 'headers', + 'body', + 'mode', + 'credentials', + 'cache', + 'redirect', + 'referrer', + 'referrerPolicy', + 'integrity', + 'keepalive', + 'signal', +]; + /** * Collects Request options to object * @param {Request} request * @returns {Object} data object */ export const getRequestData = (request) => { - const REQUEST_INIT_OPTIONS = [ - 'url', - 'method', - 'headers', - 'body', - 'mode', - 'credentials', - 'cache', - 'redirect', - 'referrer', - 'integrity', - ]; - const entries = REQUEST_INIT_OPTIONS + const requestInitOptions = getRequestProps(); + const entries = requestInitOptions .map((key) => { // if request has no such option, value will be undefined const value = request[key]; @@ -86,22 +96,7 @@ export const getXhrData = (method, url, async, user, password) => { export const parseMatchProps = (propsToMatchStr) => { const PROPS_DIVIDER = ' '; const PAIRS_MARKER = ':'; - const LEGAL_MATCH_PROPS = [ - 'method', - 'url', - 'headers', - 'body', - 'mode', - 'credentials', - 'cache', - 'redirect', - 'referrer', - 'referrerPolicy', - 'integrity', - 'keepalive', - 'signal', - 'async', - ]; + const LEGAL_MATCH_PROPS = getRequestProps(); const propsObj = {}; const props = propsToMatchStr.split(PROPS_DIVIDER); diff --git a/src/helpers/set-property-access.js b/src/helpers/set-property-access.js deleted file mode 100644 index 5ccf4e91..00000000 --- a/src/helpers/set-property-access.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Set getter and setter to property if it's configurable - * @param {Object} object target object with property - * @param {string} property property name - * @param {Object} descriptor contains getter and setter functions - * @returns {boolean} is operation successful - */ -export function setPropertyAccess(object, property, descriptor) { - const currentDescriptor = Object.getOwnPropertyDescriptor(object, property); - if (currentDescriptor && !currentDescriptor.configurable) { - return false; - } - Object.defineProperty(object, property, descriptor); - return true; -} diff --git a/src/helpers/storage-utils.js b/src/helpers/storage-utils.js index c9c43564..5769b3b7 100644 --- a/src/helpers/storage-utils.js +++ b/src/helpers/storage-utils.js @@ -1,19 +1,72 @@ +import { nativeIsNaN } from './number-utils'; +import { logMessage } from './log-message'; + +/** + * @typedef { import('../scriptlets/index').Source } Source + */ + /** * Sets item to a specified storage, if storage isn't full. + * @param {Source} source * @param {Storage} storage storage instance to set item into * @param {string} key * @param {string} value * @param {boolean} shouldLog determines if helper should log on a failed set attempt */ -export const setStorageItem = (storage, key, value, shouldLog) => { - // eslint-disable-next-line no-console - const log = console.log.bind(console); +export const setStorageItem = (source, storage, key, value) => { // setItem() may throw an exception if the storage is full. try { storage.setItem(key, value); } catch (e) { - if (shouldLog) { - log(`Unable to set sessionStorage item due to: ${e.message}`); + const message = `Unable to set sessionStorage item due to: ${e.message}`; + logMessage(source, message); + } +}; + +/** + * Gets supported storage item value + * @param {Source} source + * @param {string} value input item value + * @param {boolean} verbose if logging invalid values is required + * @returns {string|null|undefined|boolean} valid item value if ok OR null if not + */ +export const getLimitedStorageItemValue = (source, value) => { + if (!value) { + return null; + } + + let validValue; + if (value === 'undefined') { + validValue = undefined; + } else if (value === 'false') { + validValue = false; + } else if (value === 'true') { + validValue = true; + } else if (value === 'null') { + validValue = null; + } else if (value === 'emptyArr') { + validValue = '[]'; + } else if (value === 'emptyObj') { + validValue = '{}'; + } else if (value === '') { + validValue = ''; + } else if (/^\d+$/.test(value)) { + validValue = parseFloat(value); + if (nativeIsNaN(validValue)) { + logMessage(source, `Invalid storage item value: '${value}'`); + return null; + } + if (Math.abs(validValue) > 0x7FFF) { + logMessage(source, `Invalid storage item value: '${value}'`); + return null; } + } else if (value === 'yes') { + validValue = 'yes'; + } else if (value === 'no') { + validValue = 'no'; + } else { + return null; } + + return validValue; }; diff --git a/src/helpers/string-utils.js b/src/helpers/string-utils.js index 5f525270..892ef3c4 100644 --- a/src/helpers/string-utils.js +++ b/src/helpers/string-utils.js @@ -1,5 +1,10 @@ -import { nativeIsFinite, nativeIsNaN } from './number-utils'; import { isEmptyObject, getObjectEntries } from './object-utils'; +import { + nativeIsFinite, + nativeIsNaN, + getNumberFromString, + getRandomIntInclusive, +} from './number-utils'; /** * String.prototype.replaceAll polyfill @@ -287,3 +292,63 @@ export const convertTypeToString = (value) => { return output; }; + +/** + * Generate a random string, a length of the string is provided as an argument + * @param {number} length + * @returns {string} + */ +export function getRandomStrByLength(length) { + let result = ''; + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+=~'; + const charactersLength = characters.length; + for (let i = 0; i < length; i += 1) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + return result; +} + +/** + * Generate a random string + * @param {string} customResponseText + * @returns {string|null} random string or null if passed argument is invalid + */ +export function generateRandomResponse(customResponseText) { + let customResponse = customResponseText; + + if (customResponse === 'true') { + // Generate random alphanumeric string of 10 symbols + customResponse = Math.random().toString(36).slice(-10); + return customResponse; + } + + customResponse = customResponse.replace('length:', ''); + const rangeRegex = /^\d+-\d+$/; + // Return empty string if range is invalid + if (!rangeRegex.test(customResponse)) { + return null; + } + + let rangeMin = getNumberFromString(customResponse.split('-')[0]); + let rangeMax = getNumberFromString(customResponse.split('-')[1]); + + if (!nativeIsFinite(rangeMin) || !nativeIsFinite(rangeMax)) { + return null; + } + + // If rangeMin > rangeMax, swap variables + if (rangeMin > rangeMax) { + const temp = rangeMin; + rangeMin = rangeMax; + rangeMax = temp; + } + + const LENGTH_RANGE_LIMIT = 500 * 1000; + if (rangeMax > LENGTH_RANGE_LIMIT) { + return null; + } + + const length = getRandomIntInclusive(rangeMin, rangeMax); + customResponse = getRandomStrByLength(length); + return customResponse; +} diff --git a/src/helpers/throttle.js b/src/helpers/throttle.js new file mode 100644 index 00000000..45537d12 --- /dev/null +++ b/src/helpers/throttle.js @@ -0,0 +1,28 @@ +/** + * Returns a wrapper, passing the call to 'method' at maximum once per 'delay' milliseconds. + * Those calls that fall into the "cooldown" period, are ignored + * @param {Function} method + * @param {Number} delay - milliseconds + */ +export const throttle = (cb, delay) => { + let wait = false; + let savedArgs; + const wrapper = (...args) => { + if (wait) { + savedArgs = args; + return; + } + + cb(...args); + wait = true; + + setTimeout(() => { + wait = false; + if (savedArgs) { + wrapper(savedArgs); + savedArgs = null; + } + }, delay); + }; + return wrapper; +}; diff --git a/src/redirects/google-analytics-ga.js b/src/redirects/google-analytics-ga.js index f271b23d..559dc542 100644 --- a/src/redirects/google-analytics-ga.js +++ b/src/redirects/google-analytics-ga.js @@ -1,5 +1,9 @@ /* eslint-disable no-underscore-dangle */ -import { hit, noopFunc } from '../helpers/index'; +import { + hit, + noopFunc, + logMessage, +} from '../helpers/index'; /** * @redirect google-analytics-ga @@ -93,11 +97,7 @@ export function GoogleAnalyticsGa(source) { try { window.location.assign(url); } catch (e) { - // log the error only while debugging - if (source.verbose) { - // eslint-disable-next-line no-console - console.log(e); - } + logMessage(source, e); } }; @@ -128,4 +128,8 @@ GoogleAnalyticsGa.names = [ 'google-analytics_ga.js', ]; -GoogleAnalyticsGa.injections = [hit, noopFunc]; +GoogleAnalyticsGa.injections = [ + hit, + noopFunc, + logMessage, +]; diff --git a/src/redirects/google-ima3.js b/src/redirects/google-ima3.js index 8c237908..792f1c4e 100644 --- a/src/redirects/google-ima3.js +++ b/src/redirects/google-ima3.js @@ -1,5 +1,9 @@ /* eslint-disable func-names, no-underscore-dangle */ -import { hit, noopFunc } from '../helpers/index'; +import { + hit, + noopFunc, + logMessage, +} from '../helpers/index'; /** * @redirect google-ima3 @@ -114,8 +118,7 @@ export function GoogleIma3(source) { try { listener(e); } catch (r) { - // eslint-disable-next-line no-console - console.error(r); + logMessage(source, r); } } }; @@ -165,8 +168,7 @@ export function GoogleIma3(source) { try { this._dispatch(new ima.AdEvent(type)); } catch (e) { - // eslint-disable-next-line no-console - console.error(e); + logMessage(source, e); } } }; @@ -478,4 +480,8 @@ export function GoogleIma3(source) { GoogleIma3.names = ['google-ima3']; -GoogleIma3.injections = [hit, noopFunc]; +GoogleIma3.injections = [ + hit, + noopFunc, + logMessage, +]; diff --git a/src/scriptlets/abort-current-inline-script.js b/src/scriptlets/abort-current-inline-script.js index 45fc1a0a..1c17f42e 100644 --- a/src/scriptlets/abort-current-inline-script.js +++ b/src/scriptlets/abort-current-inline-script.js @@ -6,6 +6,7 @@ import { startsWith, createOnErrorHandler, hit, + logMessage, // following helpers should be imported and injected // because they are used by helpers above isEmptyObject, @@ -139,7 +140,9 @@ export function abortCurrentInlineScript(source, property, search) { const props = property.split('.'); const propIndex = props.indexOf(prop); const baseName = props[propIndex - 1]; - console.log(`The scriptlet had been executed before the ${baseName} was loaded.`); // eslint-disable-line no-console, max-len + + const message = `The scriptlet had been executed before the ${baseName} was loaded.`; + logMessage(source, message); return; } @@ -233,6 +236,7 @@ abortCurrentInlineScript.injections = [ startsWith, createOnErrorHandler, hit, + logMessage, isEmptyObject, getDescriptorAddon, ]; diff --git a/src/scriptlets/abort-on-stack-trace.js b/src/scriptlets/abort-on-stack-trace.js index 637473c4..cbcc0890 100644 --- a/src/scriptlets/abort-on-stack-trace.js +++ b/src/scriptlets/abort-on-stack-trace.js @@ -7,6 +7,7 @@ import { isValidStrPattern, matchStackTrace, getDescriptorAddon, + logMessage, shouldAbortInlineOrInjectedScript, // following helpers are needed for helpers above escapeRegExp, @@ -87,8 +88,7 @@ export function abortOnStackTrace(source, property, stack) { } if (!stack.match(/^(inlineScript|injectedScript)$/) && !isValidStrPattern(stack)) { - // eslint-disable-next-line no-console - console.log(`Invalid parameter: ${stack}`); + logMessage(source, `Invalid parameter: ${stack}`); return; } @@ -149,6 +149,7 @@ abortOnStackTrace.injections = [ escapeRegExp, matchStackTrace, getDescriptorAddon, + logMessage, toRegExp, isEmptyObject, getNativeRegexpTest, diff --git a/src/scriptlets/adjust-setInterval.js b/src/scriptlets/adjust-setInterval.js index fe44ba4f..3743a659 100644 --- a/src/scriptlets/adjust-setInterval.js +++ b/src/scriptlets/adjust-setInterval.js @@ -4,11 +4,11 @@ import { toRegExp, getBoostMultiplier, isDelayMatched, + logMessage, // following helpers are needed for helpers above nativeIsNaN, nativeIsFinite, getMatchDelay, - getWildcardSymbol, shouldMatchAnyDelay, } from '../helpers/index'; @@ -70,10 +70,9 @@ export function adjustSetInterval(source, matchCallback, matchDelay, boost) { const intervalWrapper = (callback, delay, ...args) => { // https://github.com/AdguardTeam/Scriptlets/issues/221 if (!isValidCallback(callback)) { - if (source.verbose) { - // eslint-disable-next-line no-console, max-len - console.log(`Scriptlet adjust-setInterval can not be applied because of invalid callback: '${String(callback)}'.`); - } + // eslint-disable-next-line max-len + const message = `Scriptlet can't be applied because of invalid callback: '${String(callback)}'.`; + logMessage(source, message); } else if (matchRegexp.test(callback.toString()) && isDelayMatched(matchDelay, delay)) { delay *= getBoostMultiplier(boost); hit(source); @@ -100,10 +99,10 @@ adjustSetInterval.injections = [ toRegExp, getBoostMultiplier, isDelayMatched, + logMessage, // following helpers should be injected as helpers above use them nativeIsNaN, nativeIsFinite, getMatchDelay, - getWildcardSymbol, shouldMatchAnyDelay, ]; diff --git a/src/scriptlets/adjust-setTimeout.js b/src/scriptlets/adjust-setTimeout.js index cf0d1bef..94322384 100644 --- a/src/scriptlets/adjust-setTimeout.js +++ b/src/scriptlets/adjust-setTimeout.js @@ -4,11 +4,11 @@ import { toRegExp, getBoostMultiplier, isDelayMatched, + logMessage, // following helpers are needed for helpers above nativeIsNaN, nativeIsFinite, getMatchDelay, - getWildcardSymbol, shouldMatchAnyDelay, } from '../helpers/index'; @@ -70,10 +70,9 @@ export function adjustSetTimeout(source, matchCallback, matchDelay, boost) { const timeoutWrapper = (callback, delay, ...args) => { // https://github.com/AdguardTeam/Scriptlets/issues/221 if (!isValidCallback(callback)) { - if (source.verbose) { - // eslint-disable-next-line no-console, max-len - console.log(`Scriptlet adjust-setTimeout can not be applied because of invalid callback: '${String(callback)}'.`); - } + // eslint-disable-next-line max-len + const message = `Scriptlet can't be applied because of invalid callback: '${String(callback)}'.`; + logMessage(source, message); } else if (matchRegexp.test(callback.toString()) && isDelayMatched(matchDelay, delay)) { delay *= getBoostMultiplier(boost); hit(source); @@ -102,10 +101,10 @@ adjustSetTimeout.injections = [ toRegExp, getBoostMultiplier, isDelayMatched, + logMessage, // following helpers should be injected as helpers above use them nativeIsNaN, nativeIsFinite, getMatchDelay, - getWildcardSymbol, shouldMatchAnyDelay, ]; diff --git a/src/scriptlets/close-window.js b/src/scriptlets/close-window.js index 8c691587..7083565d 100644 --- a/src/scriptlets/close-window.js +++ b/src/scriptlets/close-window.js @@ -1,4 +1,8 @@ -import { hit, toRegExp } from '../helpers/index'; +import { + hit, + toRegExp, + logMessage, +} from '../helpers/index'; /** * @scriptlet close-window @@ -28,15 +32,10 @@ import { hit, toRegExp } from '../helpers/index'; * ``` */ export function forceWindowClose(source, path = '') { - // eslint-disable-next-line no-console - const log = console.log.bind(console); - // https://github.com/AdguardTeam/Scriptlets/issues/158#issuecomment-993423036 if (typeof window.close !== 'function') { - if (source.verbose) { - log('window.close() is not a function so \'close-window\' scriptlet is unavailable'); - } - return; + const message = 'window.close() is not a function so \'close-window\' scriptlet is unavailable'; + logMessage(source, message); } const closeImmediately = () => { @@ -46,7 +45,7 @@ export function forceWindowClose(source, path = '') { } catch (e) { // log the error if window closing is impossible // https://developer.mozilla.org/en-US/docs/Web/API/Window/close - log(e); + logMessage(source, e); } }; @@ -86,4 +85,8 @@ forceWindowClose.names = [ 'ubo-window-close-if', ]; -forceWindowClose.injections = [hit, toRegExp]; +forceWindowClose.injections = [ + hit, + toRegExp, + logMessage, +]; diff --git a/src/scriptlets/debug-current-inline-script.js b/src/scriptlets/debug-current-inline-script.js index f8e2bf98..39ead498 100644 --- a/src/scriptlets/debug-current-inline-script.js +++ b/src/scriptlets/debug-current-inline-script.js @@ -5,6 +5,7 @@ import { toRegExp, createOnErrorHandler, hit, + logMessage, // following helpers should be imported and injected // because they are used by helpers above isEmptyObject, @@ -79,7 +80,9 @@ export function debugCurrentInlineScript(source, property, search) { const props = property.split('.'); const propIndex = props.indexOf(prop); const baseName = props[propIndex - 1]; - console.log(`The scriptlet had been executed before the ${baseName} was loaded.`); // eslint-disable-line no-console, max-len + + const message = `The scriptlet had been executed before the ${baseName} was loaded.`; + logMessage(message, source.verbose); return; } @@ -127,5 +130,6 @@ debugCurrentInlineScript.injections = [ toRegExp, createOnErrorHandler, hit, + logMessage, isEmptyObject, ]; diff --git a/src/scriptlets/hide-in-shadow-dom.js b/src/scriptlets/hide-in-shadow-dom.js index bfc25588..dc0a68de 100644 --- a/src/scriptlets/hide-in-shadow-dom.js +++ b/src/scriptlets/hide-in-shadow-dom.js @@ -1,9 +1,12 @@ import { hit, observeDOMChanges, - flatten, findHostElements, pierceShadowDom, + // following helpers should be imported and injected + // because they are used by helpers above + flatten, + throttle, } from '../helpers/index'; /** @@ -85,7 +88,10 @@ hideInShadowDom.names = [ hideInShadowDom.injections = [ hit, observeDOMChanges, - flatten, findHostElements, pierceShadowDom, + // following helpers should be imported and injected + // because they are used by helpers above + flatten, + throttle, ]; diff --git a/src/scriptlets/json-prune.js b/src/scriptlets/json-prune.js index 498abd07..cea27aa7 100644 --- a/src/scriptlets/json-prune.js +++ b/src/scriptlets/json-prune.js @@ -2,9 +2,9 @@ import { hit, matchStackTrace, getWildcardPropertyInChain, + logMessage, // following helpers are needed for helpers above toRegExp, - getWildcardSymbol, getNativeRegexpTest, } from '../helpers/index'; @@ -89,8 +89,7 @@ export function jsonPrune(source, propsToRemove, requiredInitialProps, stack) { if (!!stack && !matchStackTrace(stack, new Error().stack)) { return; } - // eslint-disable-next-line no-console - const log = console.log.bind(console); + const prunePaths = propsToRemove !== undefined && propsToRemove !== '' ? propsToRemove.split(/ +/) : []; @@ -111,7 +110,7 @@ export function jsonPrune(source, propsToRemove, requiredInitialProps, stack) { const matchRegex = toRegExp(requiredPaths.join('')); const shouldLog = matchRegex.test(rootString); if (shouldLog) { - log(window.location.hostname, root); + logMessage(source, `${window.location.hostname} ${root}`, true); shouldProcess = false; return shouldProcess; } @@ -157,7 +156,7 @@ export function jsonPrune(source, propsToRemove, requiredInitialProps, stack) { */ const jsonPruner = (root) => { if (prunePaths.length === 0 && requiredPaths.length === 0) { - log(window.location.hostname, root); + logMessage(source, `${window.location.hostname} ${root}`, true); return root; } @@ -178,7 +177,7 @@ export function jsonPrune(source, propsToRemove, requiredInitialProps, stack) { }); }); } catch (e) { - log(e.toString()); + logMessage(source, e); } return root; @@ -229,7 +228,7 @@ jsonPrune.injections = [ hit, matchStackTrace, getWildcardPropertyInChain, + logMessage, toRegExp, - getWildcardSymbol, getNativeRegexpTest, ]; diff --git a/src/scriptlets/log-addEventListener.js b/src/scriptlets/log-addEventListener.js index b50359e6..0d30a86f 100644 --- a/src/scriptlets/log-addEventListener.js +++ b/src/scriptlets/log-addEventListener.js @@ -4,6 +4,7 @@ import { validateListener, listenerToString, convertTypeToString, + logMessage, // following helpers are needed for helpers above objectToString, isEmptyObject, @@ -25,22 +26,20 @@ import { * ``` */ export function logAddEventListener(source) { - // eslint-disable-next-line no-console - const log = console.log.bind(console); const nativeAddEventListener = window.EventTarget.prototype.addEventListener; function addEventListenerWrapper(type, listener, ...args) { if (validateType(type) && validateListener(listener)) { - const logMessage = `addEventListener("${type}", ${listenerToString(listener)})`; - log(logMessage); + const message = `addEventListener("${type}", ${listenerToString(listener)})`; + logMessage(source, message, true); hit(source); - } else if (source.verbose) { - // logging while debugging - const logMessage = `Invalid event type or listener passed to addEventListener: + } + + // logging while debugging + const message = `Invalid event type or listener passed to addEventListener: type: ${convertTypeToString(type)} listener: ${convertTypeToString(listener)}`; - log(logMessage); - } + logMessage(source, message, true); return nativeAddEventListener.apply(this, [type, listener, ...args]); } @@ -74,6 +73,7 @@ logAddEventListener.injections = [ validateListener, listenerToString, convertTypeToString, + logMessage, objectToString, isEmptyObject, getObjectEntries, diff --git a/src/scriptlets/log-eval.js b/src/scriptlets/log-eval.js index 524c72e0..d8beeaf5 100644 --- a/src/scriptlets/log-eval.js +++ b/src/scriptlets/log-eval.js @@ -1,5 +1,5 @@ -/* eslint-disable no-console, no-eval */ -import { hit } from '../helpers/index'; +/* eslint-disable no-eval */ +import { hit, logMessage } from '../helpers/index'; /** * @scriptlet log-eval @@ -13,12 +13,11 @@ import { hit } from '../helpers/index'; * ``` */ export function logEval(source) { - const log = console.log.bind(console); // wrap eval function const nativeEval = window.eval; function evalWrapper(str) { hit(source); - log(`eval("${str}")`); + logMessage(source, `eval("${str}")`, true); return nativeEval(str); } window.eval = evalWrapper; @@ -28,7 +27,7 @@ export function logEval(source) { function FunctionWrapper(...args) { hit(source); - log(`new Function(${args.join(', ')})`); + logMessage(source, `new Function(${args.join(', ')})`, true); return nativeFunction.apply(this, [...args]); } @@ -42,4 +41,4 @@ logEval.names = [ 'log-eval', ]; -logEval.injections = [hit]; +logEval.injections = [hit, logMessage]; diff --git a/src/scriptlets/log-on-stack-trace.js b/src/scriptlets/log-on-stack-trace.js index 1cac2441..c1f3f0dc 100644 --- a/src/scriptlets/log-on-stack-trace.js +++ b/src/scriptlets/log-on-stack-trace.js @@ -2,6 +2,7 @@ import { getPropertyInChain, setPropertyAccess, hit, + logMessage, // following helpers should be imported and injected // because they are used by helpers above isEmptyObject, @@ -88,13 +89,13 @@ export function logOnStacktrace(source, property) { setPropertyAccess(base, prop, { get() { hit(source); - console.log(`%cGet %c${prop}`, 'color:red;', 'color:green;'); + logMessage(source, `Get ${prop}`, true); console.table(refineStackTrace(new Error().stack)); return value; }, set(newValue) { hit(source); - console.log(`%cSet %c${prop}`, 'color:red;', 'color:green;'); + logMessage(source, `Set ${prop}`, true); console.table(refineStackTrace(new Error().stack)); value = newValue; }, @@ -112,5 +113,6 @@ logOnStacktrace.injections = [ getPropertyInChain, setPropertyAccess, hit, + logMessage, isEmptyObject, ]; diff --git a/src/scriptlets/nowebrtc.js b/src/scriptlets/nowebrtc.js index 2290e893..3706ec92 100644 --- a/src/scriptlets/nowebrtc.js +++ b/src/scriptlets/nowebrtc.js @@ -2,6 +2,7 @@ import { hit, noopFunc, + logMessage, convertRtcConfigToString, } from '../helpers/index'; @@ -35,7 +36,9 @@ export function nowebrtc(source) { const rtcReplacement = (config) => { // eslint-disable-next-line max-len - hit(source, `Document tried to create an RTCPeerConnection: ${convertRtcConfigToString(config)}`); + const message = `Document tried to create an RTCPeerConnection: ${convertRtcConfigToString(config)}`; + logMessage(source, message); + hit(source); }; rtcReplacement.prototype = { close: noopFunc, @@ -66,5 +69,6 @@ nowebrtc.names = [ nowebrtc.injections = [ hit, noopFunc, + logMessage, convertRtcConfigToString, ]; diff --git a/src/scriptlets/prevent-adfly.js b/src/scriptlets/prevent-adfly.js index 5cdbf09f..c4852a72 100644 --- a/src/scriptlets/prevent-adfly.js +++ b/src/scriptlets/prevent-adfly.js @@ -1,5 +1,9 @@ /* eslint-disable func-names */ -import { hit, setPropertyAccess } from '../helpers/index'; +import { + hit, + setPropertyAccess, + logMessage, +} from '../helpers/index'; /** * @scriptlet prevent-adfly @@ -79,7 +83,7 @@ export function preventAdfly(source) { if (result) { hit(source); } else { - window.console.error('Failed to set up prevent-adfly scriptlet'); + logMessage(source, 'Failed to set up prevent-adfly scriptlet'); } } @@ -91,4 +95,8 @@ preventAdfly.names = [ 'ubo-adfly-defuser', ]; -preventAdfly.injections = [setPropertyAccess, hit]; +preventAdfly.injections = [ + setPropertyAccess, + hit, + logMessage, +]; diff --git a/src/scriptlets/prevent-fab-3.2.0.js b/src/scriptlets/prevent-fab-3.2.0.js index 8f891ca5..c891f3aa 100644 --- a/src/scriptlets/prevent-fab-3.2.0.js +++ b/src/scriptlets/prevent-fab-3.2.0.js @@ -1,4 +1,4 @@ -/* eslint-disable no-console, func-names, no-multi-assign */ +/* eslint-disable func-names, no-multi-assign */ import { hit, noopFunc, noopThis } from '../helpers/index'; /** diff --git a/src/scriptlets/prevent-fetch.js b/src/scriptlets/prevent-fetch.js index 6d2982a4..6dda4ffd 100644 --- a/src/scriptlets/prevent-fetch.js +++ b/src/scriptlets/prevent-fetch.js @@ -3,8 +3,8 @@ import { getFetchData, objectToString, noopPromiseResolve, - getWildcardSymbol, matchRequestProps, + logMessage, // following helpers should be imported and injected // because they are used by helpers above toRegExp, @@ -97,9 +97,6 @@ export function preventFetch(source, propsToMatch, responseBody = 'emptyObj', re return; } - // eslint-disable-next-line no-console - const log = console.log.bind(console); - let strResponseBody; if (responseBody === 'emptyObj') { strResponseBody = '{}'; @@ -111,8 +108,7 @@ export function preventFetch(source, propsToMatch, responseBody = 'emptyObj', re // Skip disallowed response types if (!(responseType === 'default' || responseType === 'opaque')) { - // eslint-disable-next-line no-console - log(`Invalid parameter: ${responseType}`); + logMessage(source, `Invalid parameter: ${responseType}`); return; } @@ -120,13 +116,12 @@ export function preventFetch(source, propsToMatch, responseBody = 'emptyObj', re let shouldPrevent = false; const fetchData = getFetchData(args); if (typeof propsToMatch === 'undefined') { - // log if no propsToMatch given - log(`fetch( ${objectToString(fetchData)} )`); + logMessage(source, `fetch( ${objectToString(fetchData)} )`, true); hit(source); return Reflect.apply(target, thisArg, args); } - shouldPrevent = matchRequestProps(propsToMatch); + shouldPrevent = matchRequestProps(source, propsToMatch, fetchData); if (shouldPrevent) { hit(source); @@ -156,8 +151,8 @@ preventFetch.injections = [ getFetchData, objectToString, noopPromiseResolve, - getWildcardSymbol, matchRequestProps, + logMessage, toRegExp, isValidStrPattern, escapeRegExp, diff --git a/src/scriptlets/prevent-refresh.js b/src/scriptlets/prevent-refresh.js index d74dc0e4..ac47402f 100644 --- a/src/scriptlets/prevent-refresh.js +++ b/src/scriptlets/prevent-refresh.js @@ -1,6 +1,7 @@ import { hit, getNumberFromString, + logMessage, // following helpers are needed for helpers above nativeIsNaN, } from '../helpers/index'; @@ -44,10 +45,7 @@ export function preventRefresh(source, delaySec) { try { metaNodes = document.querySelectorAll('meta[http-equiv="refresh"][content]'); } catch (e) { - if (source.verbose) { - // eslint-disable-next-line no-console - console.log(e); - } + logMessage(source, e); } } return Array.from(metaNodes); @@ -125,5 +123,6 @@ preventRefresh.names = [ preventRefresh.injections = [ hit, getNumberFromString, + logMessage, nativeIsNaN, ]; diff --git a/src/scriptlets/prevent-requestAnimationFrame.js b/src/scriptlets/prevent-requestAnimationFrame.js index a2f1914c..999bb1ed 100644 --- a/src/scriptlets/prevent-requestAnimationFrame.js +++ b/src/scriptlets/prevent-requestAnimationFrame.js @@ -4,6 +4,7 @@ import { parseMatchArg, isValidStrPattern, isValidCallback, + logMessage, // following helpers are needed for helpers above escapeRegExp, toRegExp, @@ -82,7 +83,6 @@ import { export function preventRequestAnimationFrame(source, match) { const nativeRequestAnimationFrame = window.requestAnimationFrame; - const log = console.log.bind(console); // eslint-disable-line no-console // logs requestAnimationFrame to console if no arguments have been specified const shouldLog = typeof match === 'undefined'; @@ -93,7 +93,7 @@ export function preventRequestAnimationFrame(source, match) { let shouldPrevent = false; if (shouldLog) { hit(source); - log(`requestAnimationFrame(${String(callback)})`); + logMessage(source, `requestAnimationFrame(${String(callback)})`, true); } else if (isValidCallback(callback) && isValidStrPattern(match)) { shouldPrevent = matchRegexp.test(callback.toString()) !== isInvertedMatch; } @@ -126,6 +126,7 @@ preventRequestAnimationFrame.injections = [ parseMatchArg, isValidStrPattern, isValidCallback, + logMessage, // following helpers should be injected as helpers above use them escapeRegExp, toRegExp, diff --git a/src/scriptlets/prevent-setInterval.js b/src/scriptlets/prevent-setInterval.js index 04a80ff1..8f9f1fa7 100644 --- a/src/scriptlets/prevent-setInterval.js +++ b/src/scriptlets/prevent-setInterval.js @@ -2,6 +2,7 @@ import { hit, noopFunc, isPreventionNeeded, + logMessage, // following helpers are needed for helpers above toRegExp, startsWith, @@ -126,7 +127,6 @@ export function preventSetInterval(source, matchCallback, matchDelay) { const isProxySupported = typeof Proxy !== 'undefined'; const nativeInterval = window.setInterval; - const log = console.log.bind(console); // eslint-disable-line no-console // logs setIntervals to console if no arguments have been specified const shouldLog = ((typeof matchCallback === 'undefined') && (typeof matchDelay === 'undefined')); @@ -136,7 +136,7 @@ export function preventSetInterval(source, matchCallback, matchDelay) { if (shouldLog) { hit(source); // https://github.com/AdguardTeam/Scriptlets/issues/105 - log(`setInterval(${String(callback)}, ${delay})`); + logMessage(source, `setInterval(${String(callback)}, ${delay})`, true); } else { shouldPrevent = isPreventionNeeded({ callback, @@ -159,7 +159,7 @@ export function preventSetInterval(source, matchCallback, matchDelay) { if (shouldLog) { hit(source); // https://github.com/AdguardTeam/Scriptlets/issues/105 - log(`setInterval(${String(callback)}, ${delay})`); + logMessage(source, `setInterval(${String(callback)}, ${delay})`, true); } else { shouldPrevent = isPreventionNeeded({ callback, @@ -205,6 +205,7 @@ preventSetInterval.injections = [ hit, noopFunc, isPreventionNeeded, + logMessage, // following helpers should be injected as helpers above use them toRegExp, startsWith, diff --git a/src/scriptlets/prevent-setTimeout.js b/src/scriptlets/prevent-setTimeout.js index 862b981f..846d3b95 100644 --- a/src/scriptlets/prevent-setTimeout.js +++ b/src/scriptlets/prevent-setTimeout.js @@ -2,6 +2,7 @@ import { hit, noopFunc, isPreventionNeeded, + logMessage, // following helpers are needed for helpers above parseMatchArg, parseDelayArg, @@ -126,7 +127,6 @@ export function preventSetTimeout(source, matchCallback, matchDelay) { const isProxySupported = typeof Proxy !== 'undefined'; const nativeTimeout = window.setTimeout; - const log = console.log.bind(console); // eslint-disable-line no-console // logs setTimeouts to console if no arguments have been specified const shouldLog = ((typeof matchCallback === 'undefined') && (typeof matchDelay === 'undefined')); @@ -136,7 +136,7 @@ export function preventSetTimeout(source, matchCallback, matchDelay) { if (shouldLog) { hit(source); // https://github.com/AdguardTeam/Scriptlets/issues/105 - log(`setTimeout(${String(callback)}, ${delay})`); + logMessage(source, `setTimeout(${String(callback)}, ${delay})`, true); } else { shouldPrevent = isPreventionNeeded({ callback, @@ -159,7 +159,7 @@ export function preventSetTimeout(source, matchCallback, matchDelay) { if (shouldLog) { hit(source); // https://github.com/AdguardTeam/Scriptlets/issues/105 - log(`setTimeout(${String(callback)}, ${delay})`); + logMessage(source, `setTimeout(${String(callback)}, ${delay})`, true); } else { shouldPrevent = isPreventionNeeded({ callback, @@ -208,6 +208,7 @@ preventSetTimeout.injections = [ hit, noopFunc, isPreventionNeeded, + logMessage, // following helpers should be injected as helpers above use them parseMatchArg, parseDelayArg, diff --git a/src/scriptlets/prevent-window-open.js b/src/scriptlets/prevent-window-open.js index ca132aa3..9787f9e0 100644 --- a/src/scriptlets/prevent-window-open.js +++ b/src/scriptlets/prevent-window-open.js @@ -9,7 +9,7 @@ import { createDecoy, getPreventGetter, noopNull, - getWildcardSymbol, + logMessage, // following helpers are needed for helpers above escapeRegExp, noopFunc, @@ -82,7 +82,7 @@ import { * > For better compatibility with uBO, old syntax is not recommended to use. */ /* eslint-enable max-len */ -export function preventWindowOpen(source, match = getWildcardSymbol(), delay, replacement) { +export function preventWindowOpen(source, match = '*', delay, replacement) { // default match value is needed for preventing all window.open calls // if scriptlet runs without args const nativeOpen = window.open; @@ -92,8 +92,7 @@ export function preventWindowOpen(source, match = getWildcardSymbol(), delay, re match = Number(match) > 0; // 'delay' was 'search' prop for matching in old syntax if (!isValidStrPattern(delay)) { - // eslint-disable-next-line no-console - console.log(`Invalid parameter: ${delay}`); + logMessage(source, `Invalid parameter: ${delay}`); return nativeOpen.apply(window, [str, ...args]); } const searchRegexp = toRegExp(delay); @@ -110,19 +109,19 @@ export function preventWindowOpen(source, match = getWildcardSymbol(), delay, re const argsStr = args && args.length > 0 ? `, ${args.join(', ')}` : ''; - const logMessage = `log: window-open: ${url}${argsStr}`; - hit(source, logMessage); + const message = `window-open: ${url}${argsStr}`; + logMessage(source, message, true); + hit(source); } let shouldPrevent = false; - if (match === getWildcardSymbol()) { + if (match === '*') { shouldPrevent = true; } else if (isValidMatchStr(match)) { const { isInvertedMatch, matchRegexp } = parseMatchArg(match); shouldPrevent = matchRegexp.test(url) !== isInvertedMatch; } else { - // eslint-disable-next-line no-console - console.log(`Invalid parameter: ${match}`); + logMessage(source, `Invalid parameter: ${match}`); shouldPrevent = false; } @@ -187,7 +186,7 @@ preventWindowOpen.injections = [ createDecoy, getPreventGetter, noopNull, - getWildcardSymbol, + logMessage, noopFunc, trueFunc, startsWith, diff --git a/src/scriptlets/prevent-xhr.js b/src/scriptlets/prevent-xhr.js index 71c9fb30..e580ee15 100644 --- a/src/scriptlets/prevent-xhr.js +++ b/src/scriptlets/prevent-xhr.js @@ -1,11 +1,9 @@ import { hit, objectToString, - getWildcardSymbol, - getRandomIntInclusive, - getRandomStrByLength, generateRandomResponse, matchRequestProps, + logMessage, // following helpers should be imported and injected // because they are used by helpers above toRegExp, @@ -19,6 +17,8 @@ import { parseMatchProps, validateParsedData, getMatchPropsData, + getRandomIntInclusive, + getRandomStrByLength, } from '../helpers/index'; /* eslint-disable max-len */ @@ -95,9 +95,6 @@ export function preventXHR(source, propsToMatch, customResponseText) { return; } - // eslint-disable-next-line no-console - const log = console.log.bind(console); - let shouldPrevent = false; let response = ''; let responseText = ''; @@ -111,10 +108,10 @@ export function preventXHR(source, propsToMatch, customResponseText) { responseUrl = xhrData.url; if (typeof propsToMatch === 'undefined') { // Log if no propsToMatch given - log(`log: xhr( ${objectToString(xhrData)} )`); + logMessage(source, `xhr( ${objectToString(xhrData)} )`, true); hit(source); } else { - shouldPrevent = matchRequestProps(propsToMatch); + shouldPrevent = matchRequestProps(source, propsToMatch, xhrData); } return Reflect.apply(target, thisArg, args); @@ -138,7 +135,7 @@ export function preventXHR(source, propsToMatch, customResponseText) { if (randomText) { responseText = randomText; } else { - log(`Invalid range: ${customResponseText}`); + logMessage(source, `Invalid range: ${customResponseText}`); } } // Mock response object @@ -189,11 +186,9 @@ preventXHR.names = [ preventXHR.injections = [ hit, + logMessage, objectToString, - getWildcardSymbol, matchRequestProps, - getRandomIntInclusive, - getRandomStrByLength, generateRandomResponse, toRegExp, isValidStrPattern, @@ -206,4 +201,6 @@ preventXHR.injections = [ parseMatchProps, validateParsedData, getMatchPropsData, + getRandomIntInclusive, + getRandomStrByLength, ]; diff --git a/src/scriptlets/remove-attr.js b/src/scriptlets/remove-attr.js index 703678c3..97e7ac3e 100644 --- a/src/scriptlets/remove-attr.js +++ b/src/scriptlets/remove-attr.js @@ -2,6 +2,10 @@ import { hit, observeDOMChanges, parseFlags, + logMessage, + // following helpers should be imported and injected + // because they are used by helpers above + throttle, } from '../helpers/index'; /* eslint-disable max-len */ @@ -79,8 +83,7 @@ export function removeAttr(source, attrs, selector, applying = 'asap stay') { try { nodes = [].slice.call(document.querySelectorAll(selector)); } catch (e) { - // eslint-disable-next-line no-console - console.log(`Invalid remove-attr selector arg: '${selector}'`); + logMessage(source, `Invalid selector arg: '${selector}'`); } let removed = false; nodes.forEach((node) => { @@ -143,4 +146,8 @@ removeAttr.injections = [ hit, observeDOMChanges, parseFlags, + logMessage, + // following helpers should be imported and injected + // because they are used by helpers above + throttle, ]; diff --git a/src/scriptlets/remove-class.js b/src/scriptlets/remove-class.js index 09c6ecf9..e768cab0 100644 --- a/src/scriptlets/remove-class.js +++ b/src/scriptlets/remove-class.js @@ -1,7 +1,11 @@ import { hit, + logMessage, observeDOMChanges, parseFlags, + // following helpers should be imported and injected + // because they are used by helpers above + throttle, } from '../helpers/index'; /* eslint-disable max-len */ @@ -89,8 +93,7 @@ export function removeClass(source, classNames, selector, applying = 'asap stay' try { foundNodes = [].slice.call(document.querySelectorAll(selector)); } catch (e) { - // eslint-disable-next-line no-console - console.log(`Invalid remove-class selector arg: '${selector}'`); + logMessage(source, `Invalid selector arg: '${selector}'`); } foundNodes.forEach((n) => nodes.add(n)); } else if (selectors.length > 0) { @@ -167,6 +170,10 @@ removeClass.names = [ removeClass.injections = [ hit, + logMessage, observeDOMChanges, parseFlags, + // following helpers should be imported and injected + // because they are used by helpers above + throttle, ]; diff --git a/src/scriptlets/remove-in-shadow-dom.js b/src/scriptlets/remove-in-shadow-dom.js index e263b1a4..94ef38aa 100644 --- a/src/scriptlets/remove-in-shadow-dom.js +++ b/src/scriptlets/remove-in-shadow-dom.js @@ -1,9 +1,12 @@ import { hit, observeDOMChanges, - flatten, findHostElements, pierceShadowDom, + // following helpers should be imported and injected + // because they are used by helpers above + flatten, + throttle, } from '../helpers/index'; /** @@ -84,7 +87,10 @@ removeInShadowDom.names = [ removeInShadowDom.injections = [ hit, observeDOMChanges, - flatten, findHostElements, pierceShadowDom, + // following helpers should be imported and injected + // because they are used by helpers above + flatten, + throttle, ]; diff --git a/src/scriptlets/set-attr.js b/src/scriptlets/set-attr.js index 8cef2dfb..fd4fd5b2 100644 --- a/src/scriptlets/set-attr.js +++ b/src/scriptlets/set-attr.js @@ -2,6 +2,9 @@ import { hit, observeDOMChanges, nativeIsNaN, + // following helpers should be imported and injected + // because they are used by helpers above + throttle, } from '../helpers/index'; /* eslint-disable max-len */ @@ -57,8 +60,8 @@ export function setAttr(source, selector, attr, value = '') { // Drop strings that cant be parsed into number, negative numbers and numbers below 32767 if (value.length !== 0 && (nativeIsNaN(parseInt(value, 10)) - || parseInt(value, 10) < 0 - || parseInt(value, 10) > 0x7FFF)) { + || parseInt(value, 10) < 0 + || parseInt(value, 10) > 0x7FFF)) { return; } @@ -82,4 +85,11 @@ setAttr.names = [ 'set-attr', ]; -setAttr.injections = [hit, observeDOMChanges, nativeIsNaN]; +setAttr.injections = [ + hit, + observeDOMChanges, + nativeIsNaN, + // following helpers should be imported and injected + // because they are used by helpers above + throttle, +]; diff --git a/src/scriptlets/set-constant.js b/src/scriptlets/set-constant.js index b5740363..8fc4a950 100644 --- a/src/scriptlets/set-constant.js +++ b/src/scriptlets/set-constant.js @@ -1,5 +1,6 @@ import { hit, + logMessage, noopArray, noopObject, noopFunc, @@ -89,8 +90,6 @@ export function setConstant(source, property, value, stack) { || !matchStackTrace(stack, new Error().stack)) { return; } - // eslint-disable-next-line no-console - const log = console.log.bind(console); const emptyArr = noopArray(); const emptyObj = noopObject(); @@ -161,9 +160,8 @@ export function setConstant(source, property, value, stack) { if (origDescriptor instanceof Object) { // This check is required to avoid defining non-configurable props if (!origDescriptor.configurable) { - if (source.verbose) { - log(`set-constant: property '${prop}' is not configurable`); - } + const message = `set-constant: property '${prop}' is not configurable`; + logMessage(source, message); return false; } @@ -278,6 +276,7 @@ setConstant.names = [ ]; setConstant.injections = [ hit, + logMessage, noopArray, noopObject, noopFunc, diff --git a/src/scriptlets/set-cookie-reload.js b/src/scriptlets/set-cookie-reload.js index 128126fb..b7d83ce6 100644 --- a/src/scriptlets/set-cookie-reload.js +++ b/src/scriptlets/set-cookie-reload.js @@ -1,5 +1,6 @@ import { hit, + logMessage, nativeIsNaN, isCookieSetWithValue, getLimitedCookieValue, @@ -50,16 +51,13 @@ export function setCookieReload(source, name, value, path = '/') { return; } - // eslint-disable-next-line no-console - const log = console.log.bind(console); - - const validValue = getLimitedCookieValue(value); + const validValue = getLimitedCookieValue(source, value); if (validValue === null) { - log(`Invalid cookie value: '${validValue}'`); + logMessage(source, `Invalid cookie value: '${validValue}'`); return; } - const cookieData = concatCookieNameValuePath(name, validValue, path); + const cookieData = concatCookieNameValuePath(source, name, validValue, path); if (cookieData) { document.cookie = cookieData; @@ -79,6 +77,7 @@ setCookieReload.names = [ setCookieReload.injections = [ hit, + logMessage, nativeIsNaN, isCookieSetWithValue, getLimitedCookieValue, diff --git a/src/scriptlets/set-cookie.js b/src/scriptlets/set-cookie.js index c686ef49..87e7eac1 100644 --- a/src/scriptlets/set-cookie.js +++ b/src/scriptlets/set-cookie.js @@ -1,5 +1,6 @@ import { hit, + logMessage, nativeIsNaN, isCookieSetWithValue, getLimitedCookieValue, @@ -46,16 +47,13 @@ import { */ /* eslint-enable max-len */ export function setCookie(source, name, value, path = '/') { - // eslint-disable-next-line no-console - const log = console.log.bind(console); - - const validValue = getLimitedCookieValue(value); + const validValue = getLimitedCookieValue(source, value); if (validValue === null) { - log(`Invalid cookie value: '${validValue}'`); + logMessage(source, `Invalid cookie value: '${validValue}'`); return; } - const cookieData = concatCookieNameValuePath(name, validValue, path); + const cookieData = concatCookieNameValuePath(source, name, validValue, path); if (cookieData) { hit(source); @@ -69,6 +67,7 @@ setCookie.names = [ setCookie.injections = [ hit, + logMessage, nativeIsNaN, isCookieSetWithValue, getLimitedCookieValue, diff --git a/src/scriptlets/set-local-storage-item.js b/src/scriptlets/set-local-storage-item.js index 9614b5cb..9211cef8 100644 --- a/src/scriptlets/set-local-storage-item.js +++ b/src/scriptlets/set-local-storage-item.js @@ -1,7 +1,9 @@ import { hit, + logMessage, nativeIsNaN, setStorageItem, + getLimitedStorageItemValue, } from '../helpers/index'; /* eslint-disable max-len */ @@ -41,52 +43,19 @@ import { /* eslint-enable max-len */ export function setLocalStorageItem(source, key, value) { - // eslint-disable-next-line no-console - const log = console.log.bind(console); - if (typeof key === 'undefined') { - log('Item key should be specified.'); - return; - } - - if (typeof value === 'undefined') { - log('Item value should be specified.'); + logMessage(source, 'Item key should be specified.'); return; } - let keyValue; - if (value === 'undefined') { - keyValue = undefined; - } else if (value === 'false') { - keyValue = false; - } else if (value === 'true') { - keyValue = true; - } else if (value === 'null') { - keyValue = null; - } else if (value === 'emptyArr') { - keyValue = '[]'; - } else if (value === 'emptyObj') { - keyValue = '{}'; - } else if (value === '') { - keyValue = ''; - } else if (/^\d+$/.test(value)) { - keyValue = parseFloat(value); - if (nativeIsNaN(keyValue)) { - return; - } - if (Math.abs(keyValue) > 0x7FFF) { - return; - } - } else if (value === 'yes') { - keyValue = 'yes'; - } else if (value === 'no') { - keyValue = 'no'; - } else { + const validValue = getLimitedStorageItemValue(source, value); + if (validValue === null) { + logMessage(source, `Invalid cookie value: '${validValue}'`); return; } const { localStorage } = window; - setStorageItem(localStorage, key, keyValue, source.verbose); + setStorageItem(source, localStorage, key, validValue); hit(source); } @@ -96,6 +65,8 @@ setLocalStorageItem.names = [ setLocalStorageItem.injections = [ hit, + logMessage, nativeIsNaN, setStorageItem, + getLimitedStorageItemValue, ]; diff --git a/src/scriptlets/set-popads-dummy.js b/src/scriptlets/set-popads-dummy.js index 6e191a62..1792e514 100644 --- a/src/scriptlets/set-popads-dummy.js +++ b/src/scriptlets/set-popads-dummy.js @@ -1,4 +1,4 @@ -/* eslint-disable no-console, func-names, no-multi-assign */ +/* eslint-disable func-names, no-multi-assign */ import { hit } from '../helpers/index'; /** diff --git a/src/scriptlets/set-session-storage-item.js b/src/scriptlets/set-session-storage-item.js index faf5a018..d2bc0e26 100644 --- a/src/scriptlets/set-session-storage-item.js +++ b/src/scriptlets/set-session-storage-item.js @@ -1,7 +1,9 @@ import { hit, + logMessage, nativeIsNaN, setStorageItem, + getLimitedStorageItemValue, } from '../helpers/index'; /* eslint-disable max-len */ @@ -41,52 +43,19 @@ import { /* eslint-enable max-len */ export function setSessionStorageItem(source, key, value) { - // eslint-disable-next-line no-console - const log = console.log.bind(console); - if (typeof key === 'undefined') { - log('Item key should be specified.'); - return; - } - - if (typeof value === 'undefined') { - log('Item value should be specified.'); + logMessage(source, 'Item key should be specified.'); return; } - let keyValue; - if (value === 'undefined') { - keyValue = undefined; - } else if (value === 'false') { - keyValue = false; - } else if (value === 'true') { - keyValue = true; - } else if (value === 'null') { - keyValue = null; - } else if (value === 'emptyArr') { - keyValue = '[]'; - } else if (value === 'emptyObj') { - keyValue = '{}'; - } else if (value === '') { - keyValue = ''; - } else if (/^\d+$/.test(value)) { - keyValue = parseFloat(value); - if (nativeIsNaN(keyValue)) { - return; - } - if (Math.abs(keyValue) > 0x7FFF) { - return; - } - } else if (value === 'yes') { - keyValue = 'yes'; - } else if (value === 'no') { - keyValue = 'no'; - } else { + const validValue = getLimitedStorageItemValue(source, value); + if (validValue === null) { + logMessage(source, `Invalid cookie value: '${validValue}'`); return; } const { sessionStorage } = window; - setStorageItem(sessionStorage, key, keyValue, source.verbose); + setStorageItem(source, sessionStorage, key, validValue); } setSessionStorageItem.names = [ @@ -95,6 +64,8 @@ setSessionStorageItem.names = [ setSessionStorageItem.injections = [ hit, + logMessage, nativeIsNaN, setStorageItem, + getLimitedStorageItemValue, ]; diff --git a/src/scriptlets/trusted-click-element.js b/src/scriptlets/trusted-click-element.js index f17972b8..871b5712 100644 --- a/src/scriptlets/trusted-click-element.js +++ b/src/scriptlets/trusted-click-element.js @@ -2,6 +2,8 @@ import { hit, toRegExp, parseCookieString, + throttle, + logMessage, } from '../helpers/index'; /* eslint-disable max-len */ @@ -64,8 +66,6 @@ export function trustedClickElement(source, selectors, extraMatch = '', delay = if (!selectors) { return; } - // eslint-disable-next-line no-console - const log = console.log.bind(console); const OBSERVER_TIMEOUT_MS = 10000; const THROTTLE_DELAY_MS = 20; @@ -81,7 +81,9 @@ export function trustedClickElement(source, selectors, extraMatch = '', delay = parsedDelay = parseInt(delay, 10); const isValidDelay = !Number.isNaN(parsedDelay) || parsedDelay < OBSERVER_TIMEOUT_MS; if (!isValidDelay) { - log(`Passed delay '${delay}' is invalid or bigger than ${OBSERVER_TIMEOUT_MS} ms`); + // eslint-disable-next-line max-len + const message = `Passed delay '${delay}' is invalid or bigger than ${OBSERVER_TIMEOUT_MS} ms`; + logMessage(source, message); return; } } @@ -248,29 +250,6 @@ export function trustedClickElement(source, selectors, extraMatch = '', delay = } }; - const throttle = (cb, ms) => { - let wait = false; - let savedArgs; - const wrapper = (...args) => { - if (wait) { - savedArgs = args; - return; - } - - cb(...args); - wait = true; - - setTimeout(() => { - wait = false; - if (savedArgs) { - wrapper(savedArgs); - savedArgs = null; - } - }, ms); - }; - return wrapper; - }; - // eslint-disable-next-line compat/compat const observer = new MutationObserver(throttle(findElements, THROTTLE_DELAY_MS)); observer.observe(document.documentElement, { @@ -299,4 +278,6 @@ trustedClickElement.injections = [ hit, toRegExp, parseCookieString, + throttle, + logMessage, ]; diff --git a/src/scriptlets/trusted-replace-fetch-response.js b/src/scriptlets/trusted-replace-fetch-response.js index 84a56e85..ab54364c 100644 --- a/src/scriptlets/trusted-replace-fetch-response.js +++ b/src/scriptlets/trusted-replace-fetch-response.js @@ -1,8 +1,8 @@ import { hit, + logMessage, getFetchData, objectToString, - getWildcardSymbol, matchRequestProps, // following helpers should be imported and injected // because they are used by helpers above @@ -85,13 +85,9 @@ export function trustedReplaceFetchResponse(source, pattern = '', replacement = return; } - // eslint-disable-next-line no-console - const log = console.log.bind(console); - // Only allow pattern as empty string for logging purposes if (pattern === '' && replacement !== '') { - const logMessage = 'log: Pattern argument should not be empty string.'; - log(source, logMessage); + logMessage(source, 'Pattern argument should not be empty string.'); return; } const shouldLog = pattern === '' && replacement === ''; @@ -106,12 +102,12 @@ export function trustedReplaceFetchResponse(source, pattern = '', replacement = if (shouldLog) { // log if no propsToMatch given - log(`fetch( ${objectToString(fetchData)} )`); + logMessage(source, `fetch( ${objectToString(fetchData)} )`, true); hit(source); return Reflect.apply(target, thisArg, args); } - shouldReplace = matchRequestProps(propsToMatch, fetchData); + shouldReplace = matchRequestProps(source, propsToMatch, fetchData); if (!shouldReplace) { return Reflect.apply(target, thisArg, args); @@ -159,7 +155,7 @@ export function trustedReplaceFetchResponse(source, pattern = '', replacement = .then((response) => { return response.text() .then((bodyText) => { - const patternRegexp = pattern === getWildcardSymbol() + const patternRegexp = pattern === '*' ? toRegExp() : toRegExp(pattern); @@ -172,7 +168,8 @@ export function trustedReplaceFetchResponse(source, pattern = '', replacement = .catch(() => { // log if response body can't be converted to a string const fetchDataStr = objectToString(fetchData); - log(`Response body can't be converted to text: ${fetchDataStr}`); + const message = `Response body can't be converted to text: ${fetchDataStr}`; + logMessage(source, message); return Reflect.apply(target, thisArg, args); }); }) @@ -193,9 +190,9 @@ trustedReplaceFetchResponse.names = [ trustedReplaceFetchResponse.injections = [ hit, + logMessage, getFetchData, objectToString, - getWildcardSymbol, matchRequestProps, toRegExp, isValidStrPattern, diff --git a/src/scriptlets/trusted-replace-xhr-response.js b/src/scriptlets/trusted-replace-xhr-response.js index ba8b112b..804756c1 100644 --- a/src/scriptlets/trusted-replace-xhr-response.js +++ b/src/scriptlets/trusted-replace-xhr-response.js @@ -1,8 +1,8 @@ import { hit, + logMessage, toRegExp, objectToString, - getWildcardSymbol, matchRequestProps, getXhrData, // following helpers should be imported and injected @@ -77,13 +77,10 @@ export function trustedReplaceXhrResponse(source, pattern = '', replacement = '' return; } - // eslint-disable-next-line no-console - const log = console.log.bind(console); - // Only allow pattern as empty string for logging purposes if (pattern === '' && replacement !== '') { - const logMessage = 'log: Pattern argument should not be empty string.'; - log(source, logMessage); + const message = 'Pattern argument should not be empty string.'; + logMessage(source, message); return; } @@ -101,13 +98,13 @@ export function trustedReplaceXhrResponse(source, pattern = '', replacement = '' if (shouldLog) { // Log if no propsToMatch given - const logMessage = `log: xhr( ${objectToString(xhrData)} )`; - log(logMessage); + const message = `log: xhr( ${objectToString(xhrData)} )`; + logMessage(source, message, true); hit(source); return Reflect.apply(target, thisArg, args); } - shouldReplace = matchRequestProps(propsToMatch, xhrData); + shouldReplace = matchRequestProps(source, propsToMatch, xhrData); // Trap setRequestHeader of target xhr object to mimic request headers later if (shouldReplace) { @@ -161,7 +158,7 @@ export function trustedReplaceXhrResponse(source, pattern = '', replacement = '' return; } - const patternRegexp = pattern === getWildcardSymbol() + const patternRegexp = pattern === '*' ? toRegExp() : toRegExp(pattern); @@ -233,9 +230,9 @@ trustedReplaceXhrResponse.names = [ trustedReplaceXhrResponse.injections = [ hit, + logMessage, toRegExp, objectToString, - getWildcardSymbol, matchRequestProps, getXhrData, getMatchPropsData, diff --git a/src/scriptlets/trusted-set-cookie.js b/src/scriptlets/trusted-set-cookie.js index a4e6f52f..64eda3b6 100644 --- a/src/scriptlets/trusted-set-cookie.js +++ b/src/scriptlets/trusted-set-cookie.js @@ -1,5 +1,6 @@ import { hit, + logMessage, nativeIsNaN, isCookieSetWithValue, concatCookieNameValuePath, @@ -72,16 +73,13 @@ import { /* eslint-enable max-len */ export function trustedSetCookie(source, name, value, offsetExpiresSec = '', reload = 'false', path = '/') { - // eslint-disable-next-line no-console - const log = console.log.bind(console); - if (typeof name === 'undefined') { - log('Cookie name should be specified.'); + logMessage(source, 'Cookie name should be specified.'); return; } if (typeof value === 'undefined') { - log('Cookie value should be specified.'); + logMessage(source, 'Cookie value should be specified.'); return; } @@ -96,7 +94,7 @@ export function trustedSetCookie(source, name, value, offsetExpiresSec = '', rel const parsedValue = parseKeywordValue(value); - let cookieToSet = concatCookieNameValuePath(name, parsedValue, path); + let cookieToSet = concatCookieNameValuePath(source, name, parsedValue, path); if (!cookieToSet) { return; } @@ -119,7 +117,8 @@ export function trustedSetCookie(source, name, value, offsetExpiresSec = '', rel // If offsetExpiresSec has been parsed to NaN - do not set cookie at all if (Number.isNaN(parsedOffsetExpiresSec)) { - log(`log: Invalid offsetExpiresSec value: ${offsetExpiresSec}`); + const message = `log: Invalid offsetExpiresSec value: ${offsetExpiresSec}`; + logMessage(source, message); return; } } @@ -147,6 +146,7 @@ trustedSetCookie.names = [ trustedSetCookie.injections = [ hit, + logMessage, nativeIsNaN, isCookieSetWithValue, concatCookieNameValuePath, diff --git a/src/scriptlets/trusted-set-local-storage-item.js b/src/scriptlets/trusted-set-local-storage-item.js index 082290d9..3ffefecd 100644 --- a/src/scriptlets/trusted-set-local-storage-item.js +++ b/src/scriptlets/trusted-set-local-storage-item.js @@ -1,5 +1,6 @@ import { hit, + logMessage, nativeIsNaN, setStorageItem, parseKeywordValue, @@ -54,23 +55,20 @@ import { /* eslint-enable max-len */ export function trustedSetLocalStorageItem(source, key, value) { - // eslint-disable-next-line no-console - const log = console.log.bind(console); - if (typeof key === 'undefined') { - log('Item key should be specified.'); + logMessage(source, 'Item key should be specified.'); return; } if (typeof value === 'undefined') { - log('Item value should be specified.'); + logMessage(source, 'Item value should be specified.'); return; } const parsedValue = parseKeywordValue(value); const { localStorage } = window; - setStorageItem(localStorage, key, parsedValue, source.verbose); + setStorageItem(source, localStorage, key, parsedValue); hit(source); } @@ -81,6 +79,7 @@ trustedSetLocalStorageItem.names = [ trustedSetLocalStorageItem.injections = [ hit, + logMessage, nativeIsNaN, setStorageItem, parseKeywordValue, diff --git a/src/scriptlets/xml-prune.js b/src/scriptlets/xml-prune.js index c1de27b3..af62fecf 100644 --- a/src/scriptlets/xml-prune.js +++ b/src/scriptlets/xml-prune.js @@ -1,5 +1,6 @@ import { hit, + logMessage, toRegExp, startsWith, endsWith, @@ -65,8 +66,7 @@ export function xmlPrune(source, propsToRemove, optionalProp = '', urlToMatch) { } let shouldPruneResponse = true; - // eslint-disable-next-line no-console - const log = console.log.bind(console); + if (!propsToRemove) { // If "propsToRemove" is not defined, then response shouldn't be pruned // but it should be logged in browser console @@ -125,7 +125,9 @@ export function xmlPrune(source, propsToRemove, optionalProp = '', urlToMatch) { thisArg.removeEventListener('readystatechange', pruneResponse); if (!shouldPruneResponse) { if (isXML(response)) { - log(`XMLHttpRequest.open() URL: ${xhrURL}\nresponse: ${response}`); + // eslint-disable-next-line max-len + const message = `XMLHttpRequest.open() URL: ${xhrURL}\nresponse: ${response}`; + logMessage(message); } } else { const prunedResponseContent = pruneXML(response); @@ -169,7 +171,7 @@ export function xmlPrune(source, propsToRemove, optionalProp = '', urlToMatch) { return response.text().then((text) => { if (!shouldPruneResponse) { if (isXML(text)) { - log(`fetch URL: ${fetchURL}\nresponse text: ${text}`); + logMessage(`fetch URL: ${fetchURL}\nresponse text: ${text}`); } return Reflect.apply(target, thisArg, args); } @@ -182,7 +184,7 @@ export function xmlPrune(source, propsToRemove, optionalProp = '', urlToMatch) { headers: response.headers, }); } - // In case if response shouldn't be pruned + // If response shouldn't be pruned // pruneXML sets shouldPruneResponse to false // so it's necessary to set it to true again // otherwise response will be only logged @@ -211,6 +213,7 @@ xmlPrune.names = [ xmlPrune.injections = [ hit, + logMessage, toRegExp, startsWith, endsWith, diff --git a/tests/scriptlets/prevent-xhr.test.js b/tests/scriptlets/prevent-xhr.test.js index 981db08c..ccfae921 100644 --- a/tests/scriptlets/prevent-xhr.test.js +++ b/tests/scriptlets/prevent-xhr.test.js @@ -1,6 +1,6 @@ /* eslint-disable no-underscore-dangle, no-console */ import { runScriptlet, clearGlobalProps } from '../helpers'; -import { startsWith } from '../../src/helpers/string-utils'; +import { startsWith, logMessage } from '../../src/helpers'; const { test, module } = QUnit; const name = 'prevent-xhr'; @@ -549,7 +549,7 @@ if (isSupported) { try { createImg.setAttribute('src', window.URL.createObjectURL(xhr.response)); } catch (error) { - console.error(error); + logMessage(error); } document.body.appendChild(createImg); assert.strictEqual(xhr.readyState, 4, 'Response done');