Improve `spoof-css` scriptlet

This commit is contained in:
Raymond Hill 2024-03-20 09:31:17 -04:00
parent 466126704c
commit 9fd80cf6dd
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
1 changed files with 20 additions and 11 deletions

View File

@ -22,11 +22,11 @@
web page context. web page context.
*/ */
/* eslint no-prototype-builtins: 0 */
// Externally added to the private namespace in which scriptlets execute. // Externally added to the private namespace in which scriptlets execute.
/* global scriptletGlobals */ /* global scriptletGlobals */
'use strict';
export const builtinScriptlets = []; export const builtinScriptlets = [];
/******************************************************************************* /*******************************************************************************
@ -424,7 +424,8 @@ function abortCurrentScriptCore(
if ( e instanceof HTMLScriptElement === false ) { return; } if ( e instanceof HTMLScriptElement === false ) { return; }
if ( e === thisScript ) { return; } if ( e === thisScript ) { return; }
if ( context !== '' && reContext.test(e.src) === false ) { if ( context !== '' && reContext.test(e.src) === false ) {
if ( debug === 'nomatch' || debug === 'all' ) { debugger; } // jshint ignore: line // eslint-disable-next-line no-debugger
if ( debug === 'nomatch' || debug === 'all' ) { debugger; }
return; return;
} }
if ( safe.logLevel > 1 && context !== '' ) { if ( safe.logLevel > 1 && context !== '' ) {
@ -432,17 +433,20 @@ function abortCurrentScriptCore(
} }
const scriptText = getScriptText(e); const scriptText = getScriptText(e);
if ( reNeedle.test(scriptText) === false ) { if ( reNeedle.test(scriptText) === false ) {
if ( debug === 'nomatch' || debug === 'all' ) { debugger; } // jshint ignore: line // eslint-disable-next-line no-debugger
if ( debug === 'nomatch' || debug === 'all' ) { debugger; }
return; return;
} }
if ( safe.logLevel > 1 ) { if ( safe.logLevel > 1 ) {
safe.uboLog(logPrefix, `Matched text\n${scriptText}`); safe.uboLog(logPrefix, `Matched text\n${scriptText}`);
} }
if ( debug === 'match' || debug === 'all' ) { debugger; } // jshint ignore: line // eslint-disable-next-line no-debugger
if ( debug === 'match' || debug === 'all' ) { debugger; }
safe.uboLog(logPrefix, 'Aborted'); safe.uboLog(logPrefix, 'Aborted');
throw new ReferenceError(exceptionToken); throw new ReferenceError(exceptionToken);
}; };
if ( debug === 'install' ) { debugger; } // jshint ignore: line // eslint-disable-next-line no-debugger
if ( debug === 'install' ) { debugger; }
try { try {
Object.defineProperty(owner, prop, { Object.defineProperty(owner, prop, {
get: function() { get: function() {
@ -895,7 +899,6 @@ function objectFindOwnerFn(
owner = owner[prop]; owner = owner[prop];
chain = chain.slice(pos + 1); chain = chain.slice(pos + 1);
} }
return true;
} }
/******************************************************************************/ /******************************************************************************/
@ -1644,7 +1647,7 @@ function addEventListenerDefuser(
const matchesEither = matchesType || matchesHandler; const matchesEither = matchesType || matchesHandler;
const matchesBoth = matchesType && matchesHandler; const matchesBoth = matchesType && matchesHandler;
if ( debug === 1 && matchesBoth || debug === 2 && matchesEither ) { if ( debug === 1 && matchesBoth || debug === 2 && matchesEither ) {
debugger; // jshint ignore:line debugger; // eslint-disable-line no-debugger
} }
if ( matchesBoth && targetSelector !== undefined ) { if ( matchesBoth && targetSelector !== undefined ) {
if ( elementMatches(thisArg) === false ) { return false; } if ( elementMatches(thisArg) === false ) { return false; }
@ -3438,7 +3441,7 @@ function hrefSanitizer(
return elem.textContent return elem.textContent
.replace(/^[^\x21-\x7e]+/, '') // remove leading invalid characters .replace(/^[^\x21-\x7e]+/, '') // remove leading invalid characters
.replace(/[^\x21-\x7e]+$/, '') // remove trailing invalid characters .replace(/[^\x21-\x7e]+$/, '') // remove trailing invalid characters
; ;
} }
return ''; return '';
}; };
@ -3578,6 +3581,7 @@ function spoofCSS(
const logPrefix = safe.makeLogPrefix('spoof-css', selector, ...args); const logPrefix = safe.makeLogPrefix('spoof-css', selector, ...args);
const canDebug = scriptletGlobals.canDebug; const canDebug = scriptletGlobals.canDebug;
const shouldDebug = canDebug && propToValueMap.get('debug') || 0; const shouldDebug = canDebug && propToValueMap.get('debug') || 0;
const instanceProperties = [ 'cssText', 'length', 'parentRule' ];
const spoofStyle = (prop, real) => { const spoofStyle = (prop, real) => {
const normalProp = toCamelCase(prop); const normalProp = toCamelCase(prop);
const shouldSpoof = propToValueMap.has(normalProp); const shouldSpoof = propToValueMap.has(normalProp);
@ -3594,7 +3598,8 @@ function spoofCSS(
}; };
self.getComputedStyle = new Proxy(self.getComputedStyle, { self.getComputedStyle = new Proxy(self.getComputedStyle, {
apply: function(target, thisArg, args) { apply: function(target, thisArg, args) {
if ( shouldDebug !== 0 ) { debugger; } // jshint ignore: line // eslint-disable-next-line no-debugger
if ( shouldDebug !== 0 ) { debugger; }
const style = Reflect.apply(target, thisArg, args); const style = Reflect.apply(target, thisArg, args);
const targetElements = new WeakSet(document.querySelectorAll(selector)); const targetElements = new WeakSet(document.querySelectorAll(selector));
if ( targetElements.has(args[0]) === false ) { return style; } if ( targetElements.has(args[0]) === false ) { return style; }
@ -3608,6 +3613,9 @@ function spoofCSS(
} }
return cloackFunc(target[prop], target, prop); return cloackFunc(target[prop], target, prop);
} }
if ( instanceProperties.includes(prop) ) {
return Reflect.get(target, prop);
}
return spoofStyle(prop, Reflect.get(target, prop, receiver)); return spoofStyle(prop, Reflect.get(target, prop, receiver));
}, },
getOwnPropertyDescriptor(target, prop) { getOwnPropertyDescriptor(target, prop) {
@ -3633,7 +3641,8 @@ function spoofCSS(
}); });
Element.prototype.getBoundingClientRect = new Proxy(Element.prototype.getBoundingClientRect, { Element.prototype.getBoundingClientRect = new Proxy(Element.prototype.getBoundingClientRect, {
apply: function(target, thisArg, args) { apply: function(target, thisArg, args) {
if ( shouldDebug !== 0 ) { debugger; } // jshint ignore: line // eslint-disable-next-line no-debugger
if ( shouldDebug !== 0 ) { debugger; }
const rect = Reflect.apply(target, thisArg, args); const rect = Reflect.apply(target, thisArg, args);
const targetElements = new WeakSet(document.querySelectorAll(selector)); const targetElements = new WeakSet(document.querySelectorAll(selector));
if ( targetElements.has(thisArg) === false ) { return rect; } if ( targetElements.has(thisArg) === false ) { return rect; }