soiz1's picture
Upload 150 files
bee6636 verified
import { iswindow } from "..";
import { SCRAMJETCLIENT } from "../../symbols";
import { ScramjetClient } from "../client";
import { config } from "../../shared";
// import { argdbg } from "./err";
import { indirectEval } from "./eval";
export function createWrapFn(client: ScramjetClient, self: typeof globalThis) {
return function (identifier: any, strict: boolean) {
if (identifier === self) return client.globalProxy;
if (identifier === self.location) return client.locationProxy;
if (identifier === eval) return indirectEval.bind(client, strict);
if (iswindow) {
if (identifier === self.parent) {
if (SCRAMJETCLIENT in self.parent) {
// ... then we're in a subframe, and the parent frame is also in a proxy context, so we should return its proxy
return self.parent[SCRAMJETCLIENT].globalProxy;
} else {
// ... then we should pretend we aren't nested and return the current window
return client.globalProxy;
}
} else if (identifier === self.document) {
return client.documentProxy;
} else if (identifier === self.top) {
// instead of returning top, we need to return the uppermost parent that's inside a scramjet context
let current = self;
for (;;) {
const test = current.parent.self;
if (test === current) break; // there is no parent, actual or emulated.
// ... then `test` represents a window outside of the proxy context, and therefore `current` is the topmost window in the proxy context
if (!(SCRAMJETCLIENT in test)) break;
// test is also insde a proxy, so we should continue up the chain
current = test;
}
return current[SCRAMJETCLIENT].globalProxy;
}
}
return identifier;
};
}
export const order = 4;
export default function (client: ScramjetClient, self: typeof globalThis) {
// the main magic of the proxy. all attempts to access any "banned objects" will be redirected here, and instead served a proxy object
// this contrasts from how other proxies will leave the root object alone and instead attempt to catch every member access
// this presents some issues (see element.ts), but makes us a good bit faster at runtime!
Object.defineProperty(self, config.globals.wrapfn, {
value: client.wrapfn,
writable: false,
configurable: false,
});
Object.defineProperty(self, config.globals.wrapthisfn, {
value: function (i) {
if (i === self) return client.globalProxy;
return i;
},
writable: false,
configurable: false,
});
self.$scramitize = function (v) {
if (v === self) debugger;
if (v === location) debugger;
if (iswindow) {
if (v === self.parent) debugger;
if (v === self.document) debugger;
if (v === self.top) debugger;
}
if (typeof v === "string" && v.includes("scramjet")) debugger;
if (typeof v === "string" && v.includes(location.origin)) debugger;
return v;
};
// location = "..." can't be rewritten as wrapfn(location) = ..., so instead it will actually be rewritten as
// ((t)=>$scramjet$tryset(location,"+=",t)||location+=t)(...);
// it has to be a discrete function because there's always the possibility that "location" is a local variable
// we have to use an IIFE to avoid duplicating side-effects in the getter
Object.defineProperty(self, config.globals.trysetfn, {
value: function (lhs: any, op: string, rhs: any) {
if (lhs instanceof Location) {
// @ts-ignore
locationProxy.href = rhs;
return true;
}
},
writable: false,
configurable: false,
});
}