feat: start proxying a lot more things & scramjet-data -> scramjet-attr

This commit is contained in:
Percs 2024-12-09 04:31:21 -06:00
parent ccefa04690
commit f43637fed7
3 changed files with 88 additions and 40 deletions

View file

@ -52,8 +52,8 @@ export default function (client: ScramjetClient, _self: typeof window) {
}, },
has(target, prop) { has(target, prop) {
if (typeof prop === "symbol") return Reflect.has(target, prop); if (typeof prop === "symbol") return Reflect.has(target, prop);
if (prop.startsWith("scramjet-data-")) return false; if (prop.startsWith("scramjet-attr-")) return false;
if (map[prop]?.name?.startsWith("scramjet-data-")) return false; if (map[prop]?.name?.startsWith("scramjet-attr-")) return false;
return Reflect.has(target, prop); return Reflect.has(target, prop);
}, },
@ -65,10 +65,10 @@ export default function (client: ScramjetClient, _self: typeof window) {
client.Trap("Attr.prototype.value", { client.Trap("Attr.prototype.value", {
get(ctx) { get(ctx) {
return ctx.this.ownerElement.getAttribute(ctx.this.name); return ctx.this.ownerElement?.getAttribute(ctx.this.name);
}, },
set(ctx, value) { set(ctx, value) {
return ctx.this.ownerElement.setAttribute(ctx.this.name, value); return ctx.this.ownerElement?.setAttribute(ctx.this.name, value);
}, },
}); });
} }

View file

@ -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", { client.Proxy("Element.prototype.setAttribute", {
apply(ctx) { apply(ctx) {
const [name, value] = ctx.args; const [name, value] = ctx.args;
@ -129,10 +157,16 @@ export default function (client: ScramjetClient, self: typeof window) {
if (ruleList) { if (ruleList) {
ctx.args[1] = ruleList.fn(value, client.meta, client.cookieStore); 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", { client.Proxy("Element.prototype.setAttributeNS", {
apply(ctx) { apply(ctx) {
const [_namespace, name, value] = ctx.args; 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); ctx.args[2] = ruleList.fn(value, client.meta, client.cookieStore);
nativeSetAttribute.call( nativeSetAttribute.call(
ctx.this, ctx.this,
`scramjet-data-${ctx.args[1]}`, `scramjet-attr-${ctx.args[1]}`,
value value
); );
} }
}, },
}); });
client.Proxy("Element.prototype.getAttribute", { client.Proxy("Element.prototype.removeAttribute", {
apply(ctx) { apply(ctx) {
const [name] = ctx.args; if (ctx.args[0].startsWith("scramjet-attr")) return ctx.return(undefined);
},
});
if (name.startsWith("scramjet-data")) { client.Proxy("Element.prototype.toggleAttribute", {
return ctx.return(null); apply(ctx) {
} if (ctx.args[0].startsWith("scramjet-attr")) return ctx.return(false);
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);
}
}, },
}); });
@ -195,7 +224,7 @@ export default function (client: ScramjetClient, self: typeof window) {
if (ctx.this instanceof self.HTMLScriptElement) { if (ctx.this instanceof self.HTMLScriptElement) {
const scriptSource = client.natives[ const scriptSource = client.natives[
"Element.prototype.getAttribute" "Element.prototype.getAttribute"
].call(ctx.this, "scramjet-data-script-source-src"); ].call(ctx.this, "scramjet-attr-script-source-src");
if (scriptSource) { if (scriptSource) {
return atob(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", { client.Proxy("Element.prototype.getHTML", {
apply(ctx) { apply(ctx) {
ctx.return(unrewriteHtml(ctx.call())); ctx.return(unrewriteHtml(ctx.call()));
@ -380,18 +422,24 @@ export default function (client: ScramjetClient, self: typeof window) {
}, },
}); });
client.Proxy("DOMParser.prototype.parseFromString", { client.Proxy(
apply(ctx) { [
if (ctx.args[1] === "text/html") { "DOMParser.prototype.parseFromString",
try { "Document.prototype.parseHTMLUnsafe",
ctx.args[0] = rewriteHtml( ],
ctx.args[0], {
client.cookieStore, apply(ctx) {
client.meta, if (ctx.args[1] === "text/html") {
false try {
); ctx.args[0] = rewriteHtml(
} catch {} ctx.args[0],
} client.cookieStore,
}, client.meta,
}); false
);
} catch {}
}
},
}
);
} }

View file

@ -81,14 +81,14 @@ export function unrewriteHtml(html: string) {
function traverse(node: ChildNode) { function traverse(node: ChildNode) {
if ("attribs" in node) { if ("attribs" in node) {
for (const key in node.attribs) { 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]) if (node.children[0] && "data" in node.children[0])
node.children[0].data = atob(node.attribs[key]); node.children[0].data = atob(node.attribs[key]);
continue; continue;
} }
if (key.startsWith("scramjet-data-")) { if (key.startsWith("scramjet-attr-")) {
node.attribs[key.slice("scramjet-data-".length)] = node.attribs[key]; node.attribs[key.slice("scramjet-attr-".length)] = node.attribs[key];
delete node.attribs[key]; delete node.attribs[key];
} }
} }
@ -219,14 +219,14 @@ function traverseParsedHtml(
else { else {
node.attribs[attr] = v; 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)) { for (const [attr, value] of Object.entries(node.attribs)) {
if (eventAttributes.includes(attr)) { if (eventAttributes.includes(attr)) {
node.attribs[`scramjet-data-${attr}`] = value; node.attribs[`scramjet-attr-${attr}`] = value;
node.attribs[attr] = rewriteJs( node.attribs[attr] = rewriteJs(
value as string, value as string,
`(inline ${attr} on element)`, `(inline ${attr} on element)`,
@ -247,8 +247,8 @@ function traverseParsedHtml(
node.children[0] !== undefined node.children[0] !== undefined
) { ) {
let js = node.children[0].data; let js = node.children[0].data;
// node.attribs[`scramjet-data-script-source-src`] = btoa(js); // node.attribs[`scramjet-attr-script-source-src`] = btoa(js);
node.attribs["scramjet-data-script-source-src"] = bytesToBase64( node.attribs["scramjet-attr-script-source-src"] = bytesToBase64(
new TextEncoder().encode(js) new TextEncoder().encode(js)
); );
const htmlcomment = /<!--[\s\S]*?-->/g; const htmlcomment = /<!--[\s\S]*?-->/g;