mirror of
https://github.com/MercuryWorkshop/scramjet.git
synced 2025-05-14 06:50:01 -04:00
rewrite location proxy (regressions!)
This commit is contained in:
parent
2bc31d7e56
commit
7f8956979a
5 changed files with 132 additions and 95 deletions
|
@ -3,55 +3,59 @@ import { SCRAMJETCLIENT } from "../../symbols";
|
|||
import { ScramjetClient } from "../client";
|
||||
import { config } from "../shared";
|
||||
|
||||
export function createWrapFn(client: ScramjetClient, self: typeof globalThis) {
|
||||
return function (identifier: any, args: any) {
|
||||
if (args && typeof args === "object" && args.length === 0)
|
||||
for (const arg of args) {
|
||||
// argdbg(arg);
|
||||
}
|
||||
if (iswindow && identifier instanceof self.Window) {
|
||||
return client.globalProxy;
|
||||
} else if (iswindow && identifier instanceof self.parent.self.Window) {
|
||||
if (SCRAMJETCLIENT in self.parent.self) {
|
||||
// ... 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.self[SCRAMJETCLIENT].globalProxy;
|
||||
} else {
|
||||
// ... then we should pretend we aren't nested and return the current window
|
||||
return client.globalProxy;
|
||||
}
|
||||
} else if (iswindow && identifier instanceof self.top.self.Window) {
|
||||
// instead of returning top, we need to return the uppermost parent that's inside a scramjet context
|
||||
let current = self.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.window;
|
||||
} else if (
|
||||
(iswindow && identifier instanceof self.Location) ||
|
||||
(isworker && identifier instanceof self.WorkerLocation)
|
||||
) {
|
||||
return client.locationProxy;
|
||||
} else if (iswindow && identifier instanceof self.Document) {
|
||||
return client.documentProxy;
|
||||
} else if (isworker && identifier instanceof self.WorkerGlobalScope) {
|
||||
return client.globalProxy;
|
||||
}
|
||||
|
||||
return identifier;
|
||||
};
|
||||
}
|
||||
|
||||
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.wrapfn, {
|
||||
value: function (identifier: any, args: any) {
|
||||
if (args && typeof args === "object" && args.length === 0)
|
||||
for (const arg of args) {
|
||||
argdbg(arg);
|
||||
}
|
||||
if (iswindow && identifier instanceof self.Window) {
|
||||
return client.globalProxy;
|
||||
} else if (iswindow && identifier instanceof self.parent.self.Window) {
|
||||
if (SCRAMJETCLIENT in self.parent.self) {
|
||||
// ... 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.self[SCRAMJETCLIENT].globalProxy;
|
||||
} else {
|
||||
// ... then we should pretend we aren't nested and return the current window
|
||||
return client.globalProxy;
|
||||
}
|
||||
} else if (iswindow && identifier instanceof self.top.self.Window) {
|
||||
// instead of returning top, we need to return the uppermost parent that's inside a scramjet context
|
||||
let current = self.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.window;
|
||||
} else if (
|
||||
(iswindow && identifier instanceof self.Location) ||
|
||||
(isworker && identifier instanceof self.WorkerLocation)
|
||||
) {
|
||||
return client.locationProxy;
|
||||
} else if (iswindow && identifier instanceof self.Document) {
|
||||
return client.documentProxy;
|
||||
} else if (isworker && identifier instanceof self.WorkerGlobalScope) {
|
||||
return client.globalProxy;
|
||||
}
|
||||
|
||||
return identifier;
|
||||
},
|
||||
value: client.wrapfn,
|
||||
writable: false,
|
||||
configurable: false,
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue