From f43637fed73b523aa388d5a72357d78038b6bc28 Mon Sep 17 00:00:00 2001 From: Percs <83934299+Percslol@users.noreply.github.com> Date: Mon, 9 Dec 2024 04:31:21 -0600 Subject: [PATCH] feat: start proxying a lot more things & scramjet-data -> scramjet-attr --- src/client/dom/attr.ts | 8 +-- src/client/dom/element.ts | 106 +++++++++++++++++++++++++---------- src/shared/rewriters/html.ts | 14 ++--- 3 files changed, 88 insertions(+), 40 deletions(-) diff --git a/src/client/dom/attr.ts b/src/client/dom/attr.ts index dbcedd4..42089bf 100644 --- a/src/client/dom/attr.ts +++ b/src/client/dom/attr.ts @@ -52,8 +52,8 @@ export default function (client: ScramjetClient, _self: typeof window) { }, has(target, prop) { if (typeof prop === "symbol") return Reflect.has(target, prop); - if (prop.startsWith("scramjet-data-")) return false; - if (map[prop]?.name?.startsWith("scramjet-data-")) return false; + if (prop.startsWith("scramjet-attr-")) return false; + if (map[prop]?.name?.startsWith("scramjet-attr-")) return false; return Reflect.has(target, prop); }, @@ -65,10 +65,10 @@ export default function (client: ScramjetClient, _self: typeof window) { client.Trap("Attr.prototype.value", { get(ctx) { - return ctx.this.ownerElement.getAttribute(ctx.this.name); + return ctx.this.ownerElement?.getAttribute(ctx.this.name); }, set(ctx, value) { - return ctx.this.ownerElement.setAttribute(ctx.this.name, value); + return ctx.this.ownerElement?.setAttribute(ctx.this.name, value); }, }); } diff --git a/src/client/dom/element.ts b/src/client/dom/element.ts index 0d5174b..e941e5b 100644 --- a/src/client/dom/element.ts +++ b/src/client/dom/element.ts @@ -114,6 +114,34 @@ export default function (client: ScramjetClient, self: typeof window) { }, }); + client.Proxy("Element.prototype.getAttribute", { + apply(ctx) { + const [name] = ctx.args; + + if (name.startsWith("scramjet-attr")) { + return ctx.return(null); + } + + if (nativeHasAttribute.call(ctx.this, `scramjet-attr-${name}`)) { + const attrib = ctx.fn.call(ctx.this, `scramjet-attr-${name}`); + if (attrib === null) return ctx.return(""); + + return ctx.return(attrib); + } + }, + }); + + client.Proxy("Element.prototype.getAttributeNames", { + apply(ctx) { + const attrNames = ctx.call() as string[]; + const cleaned = attrNames.filter( + (attr) => !attr.startsWith("scramjet-attr") + ); + + ctx.return(cleaned); + }, + }); + client.Proxy("Element.prototype.setAttribute", { apply(ctx) { const [name, value] = ctx.args; @@ -129,10 +157,16 @@ export default function (client: ScramjetClient, self: typeof window) { if (ruleList) { ctx.args[1] = ruleList.fn(value, client.meta, client.cookieStore); - ctx.fn.call(ctx.this, `scramjet-data-${ctx.args[0]}`, value); + ctx.fn.call(ctx.this, `scramjet-attr-${ctx.args[0]}`, value); } }, }); + + // i actually need to do something with this + client.Proxy("Element.prototype.setAttributeNode", { + apply(ctx) {}, + }); + client.Proxy("Element.prototype.setAttributeNS", { apply(ctx) { const [_namespace, name, value] = ctx.args; @@ -150,27 +184,22 @@ export default function (client: ScramjetClient, self: typeof window) { ctx.args[2] = ruleList.fn(value, client.meta, client.cookieStore); nativeSetAttribute.call( ctx.this, - `scramjet-data-${ctx.args[1]}`, + `scramjet-attr-${ctx.args[1]}`, value ); } }, }); - client.Proxy("Element.prototype.getAttribute", { + client.Proxy("Element.prototype.removeAttribute", { apply(ctx) { - const [name] = ctx.args; + if (ctx.args[0].startsWith("scramjet-attr")) return ctx.return(undefined); + }, + }); - if (name.startsWith("scramjet-data")) { - return ctx.return(null); - } - - if (nativeHasAttribute.call(ctx.this, `scramjet-data-${name}`)) { - const attrib = ctx.fn.call(ctx.this, `scramjet-data-${name}`); - if (attrib === null) return ctx.return(""); - - return ctx.return(attrib); - } + client.Proxy("Element.prototype.toggleAttribute", { + apply(ctx) { + if (ctx.args[0].startsWith("scramjet-attr")) return ctx.return(false); }, }); @@ -195,7 +224,7 @@ export default function (client: ScramjetClient, self: typeof window) { if (ctx.this instanceof self.HTMLScriptElement) { const scriptSource = client.natives[ "Element.prototype.getAttribute" - ].call(ctx.this, "scramjet-data-script-source-src"); + ].call(ctx.this, "scramjet-attr-script-source-src"); if (scriptSource) { return atob(scriptSource); @@ -220,6 +249,19 @@ export default function (client: ScramjetClient, self: typeof window) { }, }); + client.Proxy("Element.prototype.setHTMLUnsafe", { + apply(ctx) { + try { + ctx.args[0] = rewriteHtml( + ctx.args[0], + client.cookieStore, + client.meta, + false + ); + } catch {} + }, + }); + client.Proxy("Element.prototype.getHTML", { apply(ctx) { ctx.return(unrewriteHtml(ctx.call())); @@ -380,18 +422,24 @@ export default function (client: ScramjetClient, self: typeof window) { }, }); - client.Proxy("DOMParser.prototype.parseFromString", { - apply(ctx) { - if (ctx.args[1] === "text/html") { - try { - ctx.args[0] = rewriteHtml( - ctx.args[0], - client.cookieStore, - client.meta, - false - ); - } catch {} - } - }, - }); + client.Proxy( + [ + "DOMParser.prototype.parseFromString", + "Document.prototype.parseHTMLUnsafe", + ], + { + apply(ctx) { + if (ctx.args[1] === "text/html") { + try { + ctx.args[0] = rewriteHtml( + ctx.args[0], + client.cookieStore, + client.meta, + false + ); + } catch {} + } + }, + } + ); } diff --git a/src/shared/rewriters/html.ts b/src/shared/rewriters/html.ts index f3059b3..84120f7 100644 --- a/src/shared/rewriters/html.ts +++ b/src/shared/rewriters/html.ts @@ -81,14 +81,14 @@ export function unrewriteHtml(html: string) { function traverse(node: ChildNode) { if ("attribs" in node) { for (const key in node.attribs) { - if (key == "scramjet-data-script-source-src") { + if (key == "scramjet-attr-script-source-src") { if (node.children[0] && "data" in node.children[0]) node.children[0].data = atob(node.attribs[key]); continue; } - if (key.startsWith("scramjet-data-")) { - node.attribs[key.slice("scramjet-data-".length)] = node.attribs[key]; + if (key.startsWith("scramjet-attr-")) { + node.attribs[key.slice("scramjet-attr-".length)] = node.attribs[key]; delete node.attribs[key]; } } @@ -219,14 +219,14 @@ function traverseParsedHtml( else { node.attribs[attr] = v; } - node.attribs[`scramjet-data-${attr}`] = value; + node.attribs[`scramjet-attr-${attr}`] = value; } } } } for (const [attr, value] of Object.entries(node.attribs)) { if (eventAttributes.includes(attr)) { - node.attribs[`scramjet-data-${attr}`] = value; + node.attribs[`scramjet-attr-${attr}`] = value; node.attribs[attr] = rewriteJs( value as string, `(inline ${attr} on element)`, @@ -247,8 +247,8 @@ function traverseParsedHtml( node.children[0] !== undefined ) { let js = node.children[0].data; - // node.attribs[`scramjet-data-script-source-src`] = btoa(js); - node.attribs["scramjet-data-script-source-src"] = bytesToBase64( + // node.attribs[`scramjet-attr-script-source-src`] = btoa(js); + node.attribs["scramjet-attr-script-source-src"] = bytesToBase64( new TextEncoder().encode(js) ); const htmlcomment = //g;