mirror of
https://github.com/MercuryWorkshop/scramjet.git
synced 2025-05-15 23:30:00 -04:00
refactor: everything
This commit is contained in:
parent
78e666d314
commit
506d99f9b6
37 changed files with 925 additions and 885 deletions
163
src/client/dom/element.ts
Normal file
163
src/client/dom/element.ts
Normal file
|
@ -0,0 +1,163 @@
|
|||
import { ScramjetClient } from "../client";
|
||||
import { decodeUrl } from "../shared";
|
||||
import {
|
||||
encodeUrl,
|
||||
rewriteCss,
|
||||
rewriteHtml,
|
||||
rewriteJs,
|
||||
rewriteSrcset,
|
||||
} from "../shared";
|
||||
|
||||
declare global {
|
||||
interface Element {
|
||||
$origattrs: Record<string, string>;
|
||||
}
|
||||
}
|
||||
export default function (client: ScramjetClient, self: typeof window) {
|
||||
dbg.log("RAN");
|
||||
const attrObject = {
|
||||
nonce: [self.HTMLElement],
|
||||
integrity: [self.HTMLScriptElement, self.HTMLLinkElement],
|
||||
csp: [self.HTMLIFrameElement],
|
||||
src: [
|
||||
self.HTMLImageElement,
|
||||
self.HTMLMediaElement,
|
||||
self.HTMLIFrameElement,
|
||||
self.HTMLEmbedElement,
|
||||
self.HTMLScriptElement,
|
||||
],
|
||||
href: [self.HTMLAnchorElement, self.HTMLLinkElement],
|
||||
data: [self.HTMLObjectElement],
|
||||
action: [self.HTMLFormElement],
|
||||
formaction: [self.HTMLButtonElement, self.HTMLInputElement],
|
||||
srcdoc: [self.HTMLIFrameElement],
|
||||
srcset: [self.HTMLImageElement, self.HTMLSourceElement],
|
||||
imagesrcset: [self.HTMLLinkElement],
|
||||
};
|
||||
|
||||
const attrs = Object.keys(attrObject);
|
||||
|
||||
for (const attr of attrs) {
|
||||
for (const element of attrObject[attr]) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(
|
||||
element.prototype,
|
||||
attr
|
||||
);
|
||||
Object.defineProperty(element.prototype, attr, {
|
||||
get() {
|
||||
if (["src", "data", "href", "action", "formaction"].includes(attr)) {
|
||||
return decodeUrl(descriptor.get.call(this));
|
||||
}
|
||||
|
||||
if (this.$origattrs[attr]) {
|
||||
return this.$origattrs[attr];
|
||||
}
|
||||
|
||||
return descriptor.get.call(this);
|
||||
},
|
||||
|
||||
set(value) {
|
||||
this.$origattrs[attr] = value;
|
||||
|
||||
if (["nonce", "integrity", "csp"].includes(attr)) {
|
||||
return;
|
||||
} else if (
|
||||
["src", "data", "href", "action", "formaction"].includes(attr)
|
||||
) {
|
||||
value = encodeUrl(value);
|
||||
} else if (attr === "srcdoc") {
|
||||
value = rewriteHtml(value);
|
||||
} else if (["srcset", "imagesrcset"].includes(attr)) {
|
||||
value = rewriteSrcset(value);
|
||||
}
|
||||
|
||||
descriptor.set.call(this, value);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
self.Element.prototype.$origattrs = {};
|
||||
|
||||
self.Element.prototype.getAttribute = new Proxy(
|
||||
self.Element.prototype.getAttribute,
|
||||
{
|
||||
apply(target, thisArg, argArray) {
|
||||
if (attrs.includes(argArray[0]) && thisArg.$origattrs[argArray[0]]) {
|
||||
return thisArg.$origattrs[argArray[0]];
|
||||
}
|
||||
|
||||
return Reflect.apply(target, thisArg, argArray);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
self.Element.prototype.setAttribute = new Proxy(
|
||||
self.Element.prototype.setAttribute,
|
||||
{
|
||||
apply(target, thisArg, argArray) {
|
||||
if (attrs.includes(argArray[0])) {
|
||||
thisArg.$origattrs[argArray[0]] = argArray[1];
|
||||
if (["nonce", "integrity", "csp"].includes(argArray[0])) {
|
||||
return;
|
||||
} else if (
|
||||
["src", "data", "href", "action", "formaction"].includes(
|
||||
argArray[0]
|
||||
)
|
||||
) {
|
||||
argArray[1] = encodeUrl(argArray[1]);
|
||||
} else if (argArray[0] === "srcdoc") {
|
||||
// TODO: this will rewrite with the wrong url in mind for iframes!!
|
||||
argArray[1] = rewriteHtml(argArray[1]);
|
||||
} else if (["srcset", "imagesrcset"].includes(argArray[0])) {
|
||||
argArray[1] = rewriteSrcset(argArray[1]);
|
||||
} else if (argArray[1] === "style") {
|
||||
argArray[1] = rewriteCss(argArray[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return Reflect.apply(target, thisArg, argArray);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const innerHTML = Object.getOwnPropertyDescriptor(
|
||||
self.Element.prototype,
|
||||
"innerHTML"
|
||||
);
|
||||
|
||||
Object.defineProperty(self.Element.prototype, "innerHTML", {
|
||||
set(value) {
|
||||
if (this instanceof self.HTMLScriptElement) {
|
||||
value = rewriteJs(value);
|
||||
} else if (this instanceof self.HTMLStyleElement) {
|
||||
value = rewriteCss(value);
|
||||
} else {
|
||||
value = rewriteHtml(value);
|
||||
}
|
||||
|
||||
return innerHTML.set.call(this, value);
|
||||
},
|
||||
});
|
||||
|
||||
for (const target of [
|
||||
self.Node.prototype,
|
||||
self.MutationObserver.prototype,
|
||||
self.document,
|
||||
]) {
|
||||
for (const prop in target) {
|
||||
try {
|
||||
if (typeof target[prop] === "function") {
|
||||
client.RawProxy(target, prop, {
|
||||
apply(ctx) {
|
||||
for (const i in ctx.args) {
|
||||
if (ctx.args[i] === client.documentProxy)
|
||||
ctx.args[i] = self.document;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue