From f022024291f0d5a72dd1dcec05e4ad797ed40804 Mon Sep 17 00:00:00 2001 From: Percs <83934299+Percslol@users.noreply.github.com> Date: Mon, 9 Dec 2024 10:56:45 -0600 Subject: [PATCH] feat: improve natives store and proxy element.hasattribute --- src/client/client.ts | 46 +++++++++++++++++++- src/client/dom/element.ts | 19 +++++--- src/client/shared/requests/xmlhttprequest.ts | 4 +- 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/client/client.ts b/src/client/client.ts index e3b6ec5..c3166bb 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -66,7 +66,7 @@ export class ScramjetClient { bare: BareClientType; descriptors: Record = {}; - natives: Record = {}; + natives: Record; wrapfn: (i: any, ...args: any) => any; cookieStore = new CookieStore(); @@ -120,7 +120,51 @@ export class ScramjetClient { }) ); } + this.natives = new Proxy( + {}, + { + get: (target, prop: string) => { + if (prop in target) { + return target[prop]; + } else { + const split = prop.split("."); + const realProp = split.pop(); + const realTarget = split.reduce((a, b) => a?.[b], this.global); + + if (!realTarget) return; + + const original = Reflect.get(realTarget, realProp); + target[prop] = original; + return target[prop]; + } + }, + } + ); + this.descriptors = new Proxy( + {}, + { + get: (target, prop: string) => { + if (prop in target) { + return target[prop]; + } else { + const split = prop.split("."); + const realProp = split.pop(); + const realTarget = split.reduce((a, b) => a?.[b], this.global); + + if (!realTarget) return; + + const original = nativeGetOwnPropertyDescriptor( + realTarget, + realProp + ); + target[prop] = original; + + return target[prop]; + } + }, + } + ); // eslint-disable-next-line @typescript-eslint/no-this-alias const client = this; this.meta = { diff --git a/src/client/dom/element.ts b/src/client/dom/element.ts index e941e5b..4c3b2af 100644 --- a/src/client/dom/element.ts +++ b/src/client/dom/element.ts @@ -5,10 +5,6 @@ import { unrewriteUrl, htmlRules, unrewriteHtml } from "../../shared"; import { rewriteCss, rewriteHtml, rewriteJs } from "../../shared"; export default function (client: ScramjetClient, self: typeof window) { - const _nativeGetAttribute = self.Element.prototype.getAttribute; - const nativeSetAttribute = self.Element.prototype.setAttribute; - const nativeHasAttribute = self.Element.prototype.hasAttribute; - const attrObject = { nonce: [self.HTMLElement], integrity: [self.HTMLScriptElement, self.HTMLLinkElement], @@ -122,7 +118,12 @@ export default function (client: ScramjetClient, self: typeof window) { return ctx.return(null); } - if (nativeHasAttribute.call(ctx.this, `scramjet-attr-${name}`)) { + if ( + client.natives["Element.prototype.hasAttribute"].call( + ctx.this, + `scramjet-attr-${name}` + ) + ) { const attrib = ctx.fn.call(ctx.this, `scramjet-attr-${name}`); if (attrib === null) return ctx.return(""); @@ -142,6 +143,12 @@ export default function (client: ScramjetClient, self: typeof window) { }, }); + client.Proxy("Element.prototype.hasAttribute", { + apply(ctx) { + if (ctx.args[0].startsWith("scramjet-attr")) return ctx.return(false); + }, + }); + client.Proxy("Element.prototype.setAttribute", { apply(ctx) { const [name, value] = ctx.args; @@ -182,7 +189,7 @@ export default function (client: ScramjetClient, self: typeof window) { if (ruleList) { ctx.args[2] = ruleList.fn(value, client.meta, client.cookieStore); - nativeSetAttribute.call( + client.natives["Element.prototype.setAttribute"].call( ctx.this, `scramjet-attr-${ctx.args[1]}`, value diff --git a/src/client/shared/requests/xmlhttprequest.ts b/src/client/shared/requests/xmlhttprequest.ts index 5818e50..c8eb384 100644 --- a/src/client/shared/requests/xmlhttprequest.ts +++ b/src/client/shared/requests/xmlhttprequest.ts @@ -5,9 +5,7 @@ import { ScramjetClient } from "../../client"; export default function (client: ScramjetClient, self: Self) { let worker; if (self.Worker && flagEnabled("syncxhr", client.url)) { - worker = new (client.natives["Worker"] ? client.natives["Worker"] : Worker)( - config.files.sync - ); + worker = new client.natives["Worker"](config.files.sync); } const ARGS = Symbol("xhr original args"); const HEADERS = Symbol("xhr headers");