feat: improve natives store and proxy element.hasattribute

This commit is contained in:
Percs 2024-12-09 10:56:45 -06:00
parent f43637fed7
commit f022024291
3 changed files with 59 additions and 10 deletions

View file

@ -66,7 +66,7 @@ export class ScramjetClient {
bare: BareClientType; bare: BareClientType;
descriptors: Record<string, PropertyDescriptor> = {}; descriptors: Record<string, PropertyDescriptor> = {};
natives: Record<string, any> = {}; natives: Record<string, any>;
wrapfn: (i: any, ...args: any) => any; wrapfn: (i: any, ...args: any) => any;
cookieStore = new CookieStore(); 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 // eslint-disable-next-line @typescript-eslint/no-this-alias
const client = this; const client = this;
this.meta = { this.meta = {

View file

@ -5,10 +5,6 @@ import { unrewriteUrl, htmlRules, unrewriteHtml } from "../../shared";
import { rewriteCss, rewriteHtml, rewriteJs } from "../../shared"; import { rewriteCss, rewriteHtml, rewriteJs } from "../../shared";
export default function (client: ScramjetClient, self: typeof window) { 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 = { const attrObject = {
nonce: [self.HTMLElement], nonce: [self.HTMLElement],
integrity: [self.HTMLScriptElement, self.HTMLLinkElement], integrity: [self.HTMLScriptElement, self.HTMLLinkElement],
@ -122,7 +118,12 @@ export default function (client: ScramjetClient, self: typeof window) {
return ctx.return(null); 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}`); const attrib = ctx.fn.call(ctx.this, `scramjet-attr-${name}`);
if (attrib === null) return ctx.return(""); 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", { client.Proxy("Element.prototype.setAttribute", {
apply(ctx) { apply(ctx) {
const [name, value] = ctx.args; const [name, value] = ctx.args;
@ -182,7 +189,7 @@ export default function (client: ScramjetClient, self: typeof window) {
if (ruleList) { if (ruleList) {
ctx.args[2] = ruleList.fn(value, client.meta, client.cookieStore); ctx.args[2] = ruleList.fn(value, client.meta, client.cookieStore);
nativeSetAttribute.call( client.natives["Element.prototype.setAttribute"].call(
ctx.this, ctx.this,
`scramjet-attr-${ctx.args[1]}`, `scramjet-attr-${ctx.args[1]}`,
value value

View file

@ -5,9 +5,7 @@ import { ScramjetClient } from "../../client";
export default function (client: ScramjetClient, self: Self) { export default function (client: ScramjetClient, self: Self) {
let worker; let worker;
if (self.Worker && flagEnabled("syncxhr", client.url)) { if (self.Worker && flagEnabled("syncxhr", client.url)) {
worker = new (client.natives["Worker"] ? client.natives["Worker"] : Worker)( worker = new client.natives["Worker"](config.files.sync);
config.files.sync
);
} }
const ARGS = Symbol("xhr original args"); const ARGS = Symbol("xhr original args");
const HEADERS = Symbol("xhr headers"); const HEADERS = Symbol("xhr headers");