scramjet/src/client/global.ts
2024-10-14 11:59:02 -04:00

86 lines
2.2 KiB
TypeScript

// import { encodeUrl } from "../shared";
import { iswindow } from ".";
import { SCRAMJETCLIENT } from "../symbols";
import { ScramjetClient } from "./client";
// import { config } from "../shared";
import { getOwnPropertyDescriptorHandler } from "./helpers";
import { indirectEval } from "./shared/eval";
export const UNSAFE_GLOBALS = [
"window",
"self",
"globalThis",
"this",
"parent",
"top",
"location",
"document",
"eval",
"frames",
];
export function createGlobalProxy(
client: ScramjetClient,
self: typeof globalThis
): typeof globalThis {
return new Proxy(self, {
get(target, prop) {
const value = Reflect.get(target, prop);
if (
iswindow &&
(typeof prop === "string" || typeof prop === "number") &&
!isNaN(Number(prop)) &&
value
) {
const win: Self = value.self;
// indexing into window gives you the contentWindow of the subframes for some reason
// you can't *set* it so this should always be the right value
if (SCRAMJETCLIENT in win) {
// then we've already hooked this frame and we can just send over its proxy
return win[SCRAMJETCLIENT].globalProxy;
} else {
// this can happen if it's an about:blank iframe that we've never gotten the chance to inject into
// just make a new client for it and inject
const newclient = new ScramjetClient(win);
newclient.hook();
return newclient.globalProxy;
}
}
if (prop === "$scramjet") return null;
if (typeof prop === "string" && UNSAFE_GLOBALS.includes(prop))
return client.wrapfn(value);
return value;
},
set(target, prop, value) {
if (prop === "location") {
client.url = value;
return;
}
return Reflect.set(target, prop, value);
},
has(target, prop) {
if (prop === "$scramjet") return false;
return Reflect.has(target, prop);
},
ownKeys(target) {
return Reflect.ownKeys(target).filter((key) => key !== "$scramjet");
},
defineProperty(target, property, attributes) {
if (!attributes.get && !attributes.set) {
attributes.writable = true;
}
attributes.configurable = true;
return Reflect.defineProperty(target, property, attributes);
},
getOwnPropertyDescriptor: getOwnPropertyDescriptorHandler,
});
}