mirror of
https://github.com/QuiteAFancyEmerald/Holy-Unblocker.git
synced 2025-05-12 11:30:01 -04:00
113 lines
No EOL
4.9 KiB
JavaScript
113 lines
No EOL
4.9 KiB
JavaScript
const { overrideAccessors, overrideFunction, overrideConstructor } = require("./utils");
|
|
|
|
function createDomRewriter(ctx) {
|
|
if (ctx.serviceWorker) return () => null;
|
|
if (ctx.window.Node && ctx.window.Node.prototype) {
|
|
ctx.originalAccessors.nodeBaseURI = Object.getOwnPropertyDescriptor(ctx.window.Node.prototype, 'baseURI');
|
|
ctx.originalAccessors.nodeTextContent = Object.getOwnPropertyDescriptor(ctx.window.Node.prototype, 'textContent');
|
|
};
|
|
if (ctx.window.Element && ctx.window.Element.prototype) {
|
|
ctx.originalAccessors.elementInnerHtml = Object.getOwnPropertyDescriptor(ctx.window.Element.prototype, 'innerHTML');
|
|
ctx.originalAccessors.elementOuterHtml = Object.getOwnPropertyDescriptor(ctx.window.Element.prototype, 'outerHTML');
|
|
ctx.originalFn.elementSetAttribute = ctx.window.Element.prototype.setAttribute;
|
|
ctx.originalFn.elementGetAttribute = ctx.window.Element.prototype.getAttribute;
|
|
ctx.originalFn.elementHasAttribute = ctx.window.Element.prototype.hasAttribute;
|
|
};
|
|
if (ctx.window.Audio) ctx.originalFn.Audio = ctx.window.Audio;
|
|
function rewriteTextContent() {
|
|
if (ctx.originalAccessors.nodeTextContent) {
|
|
overrideAccessors(ctx.window.Node.prototype, 'textContent', {
|
|
setter: (target, that, [ val ]) => {
|
|
switch(that.tagName) {
|
|
case 'SCRIPT':
|
|
val = ctx.processScript(val);
|
|
break;
|
|
case 'STYLE':
|
|
val = ctx.processStyle(val);
|
|
break;
|
|
};
|
|
return target.call(that, val);
|
|
},
|
|
});
|
|
};
|
|
};
|
|
function rewriteUrl() {
|
|
if (ctx.originalAccessors.nodeBaseURI) {
|
|
overrideAccessors(ctx.window.Node.prototype, 'baseURI', {
|
|
getter: (target, that) => {
|
|
const url = target.call(that);
|
|
return url.startsWith(ctx.meta.origin) ? ctx.url.unwrap(url, ctx.meta) : url;
|
|
},
|
|
});
|
|
};
|
|
};
|
|
function rewriteHtml() {
|
|
if (ctx.originalAccessors.elementInnerHtml) {
|
|
overrideAccessors(ctx.window.Element.prototype, 'innerHTML', {
|
|
getter: (target, that) => ['STYLE', 'SCRIPT'].includes(that.tagName) ? target.call(that) : ctx.html.source(target.call(that)),
|
|
setter: (target, that, [ val ]) => {
|
|
switch(that.tagName) {
|
|
case 'STYLE':
|
|
val = ctx.processStyle(val);
|
|
break;
|
|
case 'SCRIPT':
|
|
val = ctx.processScript(val);
|
|
break;
|
|
default:
|
|
val = ctx.processHtml(val);
|
|
break;
|
|
};
|
|
return target.call(that, val);
|
|
},
|
|
});
|
|
};
|
|
};
|
|
function rewriteAttribute() {
|
|
if (ctx.originalFn.elementSetAttribute) {
|
|
overrideFunction(ctx.window.Element.prototype, 'setAttribute', (target, that, args) => {
|
|
if (args[0] && args[1]) {
|
|
let data = {
|
|
attr: {
|
|
name: args[0],
|
|
value: args[1],
|
|
},
|
|
node: that,
|
|
meta: ctx.meta,
|
|
setAttribute: ctx.originalFn.elementSetAttribute.bind(that),
|
|
delete: false,
|
|
ctx,
|
|
};
|
|
const tag = ctx.html.attrs.get(that.tagName.toLowerCase()) || ctx.html.attrs.get('*');
|
|
if (tag[data.attr.name]) tag[data.attr.name](that, data);
|
|
args[0] = data.attr.name;
|
|
args[1] = data.attr.value;
|
|
};
|
|
return target.apply(that, args);
|
|
});
|
|
};
|
|
if (ctx.originalFn.elementGetAttribute) {
|
|
overrideFunction(ctx.window.Element.prototype, 'getAttribute', (target, that, args) => {
|
|
if (args[0] && ctx.originalFn.elementHasAttribute.call(that, `corrosion-attr-${args[0]}`)) args[0] = `corrosion-attr-${args[0]}`;
|
|
return target.apply(that, args);
|
|
});
|
|
};
|
|
};
|
|
function rewriteAudio() {
|
|
if (ctx.originalFn.Audio) {
|
|
overrideConstructor(ctx.window, 'Audio', (target, args) => {
|
|
if (args[0]) args[0] = ctx.url.wrap(args[0], ctx.meta);
|
|
return new target(...args);
|
|
});
|
|
};
|
|
};
|
|
return function rewriteDom() {
|
|
rewriteUrl();
|
|
rewriteTextContent();
|
|
rewriteHtml();
|
|
rewriteAttribute();
|
|
rewriteAudio();
|
|
return true;
|
|
};
|
|
};
|
|
|
|
module.exports = createDomRewriter; |