mirror of
https://github.com/MercuryWorkshop/scramjet.git
synced 2025-05-13 14:30:02 -04:00
rewrite location proxy (regressions!)
This commit is contained in:
parent
2bc31d7e56
commit
7f8956979a
5 changed files with 132 additions and 95 deletions
|
@ -1,10 +1,13 @@
|
|||
import { SCRAMJETCLIENT } from "../symbols";
|
||||
import { iswindow } from ".";
|
||||
import { ScramjetFrame } from "../controller/frame";
|
||||
import { SCRAMJETCLIENT, SCRAMJETFRAME } from "../symbols";
|
||||
import { createDocumentProxy } from "./document";
|
||||
import { createGlobalProxy } from "./global";
|
||||
import { getOwnPropertyDescriptorHandler } from "./helpers";
|
||||
import { createLocationProxy } from "./location";
|
||||
import { nativeGetOwnPropertyDescriptor } from "./natives";
|
||||
import { CookieStore, config, decodeUrl } from "./shared";
|
||||
import { createWrapFn } from "./shared/wrap";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
@ -51,6 +54,7 @@ export class ScramjetClient {
|
|||
|
||||
descriptors: Record<string, PropertyDescriptor> = {};
|
||||
natives: Record<string, any> = {};
|
||||
wrapfn: (i: any, ...args: any) => any;
|
||||
|
||||
cookieStore = new CookieStore();
|
||||
|
||||
|
@ -68,7 +72,7 @@ export class ScramjetClient {
|
|||
constructor(public global: typeof globalThis) {
|
||||
this.serviceWorker = this.global.navigator.serviceWorker;
|
||||
|
||||
if ("document" in global) {
|
||||
if (iswindow) {
|
||||
this.documentProxy = createDocumentProxy(this, global);
|
||||
|
||||
global.document[SCRAMJETCLIENT] = this;
|
||||
|
@ -76,10 +80,23 @@ export class ScramjetClient {
|
|||
|
||||
this.locationProxy = createLocationProxy(this, global);
|
||||
this.globalProxy = createGlobalProxy(this, global);
|
||||
this.wrapfn = createWrapFn(this, global);
|
||||
|
||||
global[SCRAMJETCLIENT] = this;
|
||||
}
|
||||
|
||||
get frame(): ScramjetFrame | null {
|
||||
if (!iswindow) return null;
|
||||
const frame = this.global.window.frameElement;
|
||||
|
||||
if (!frame) return null; // we're top level
|
||||
const sframe = frame[SCRAMJETFRAME];
|
||||
|
||||
if (!sframe) return null; // we're a subframe. TODO handle propagation but not now
|
||||
|
||||
return sframe;
|
||||
}
|
||||
|
||||
loadcookies(cookiestr: string) {
|
||||
this.cookieStore.load(cookiestr);
|
||||
}
|
||||
|
|
|
@ -8,11 +8,7 @@ export const order = 2;
|
|||
|
||||
export const enabled = () => self.$scramjet.config.flags.serviceworkers;
|
||||
export function disabled(client: ScramjetClient, self: Self) {
|
||||
client.Trap("navigator.serviceWorker", {
|
||||
get() {
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
Reflect.deleteProperty(Navigator.prototype, "serviceWorker");
|
||||
}
|
||||
|
||||
export default function (client: ScramjetClient, self: Self) {
|
||||
|
|
|
@ -1,44 +1,78 @@
|
|||
// @ts-nocheck
|
||||
import { ScramjetClient } from "./client";
|
||||
import { nativeGetOwnPropertyDescriptor } from "./natives";
|
||||
import { encodeUrl, decodeUrl } from "./shared";
|
||||
|
||||
export function createLocationProxy(
|
||||
client: ScramjetClient,
|
||||
self: typeof globalThis
|
||||
) {
|
||||
function createLocation() {
|
||||
const loc = new URL(client.url.href);
|
||||
// location cannot be Proxy()d
|
||||
const fakeLocation = {};
|
||||
Object.setPrototypeOf(fakeLocation, self.Location.prototype);
|
||||
fakeLocation.constructor = self.Location;
|
||||
|
||||
loc.assign = (url: string) => self.location.assign(encodeUrl(url));
|
||||
loc.reload = () => self.location.reload();
|
||||
loc.replace = (url: string) => self.location.replace(encodeUrl(url));
|
||||
loc.toString = () => loc.href;
|
||||
|
||||
return loc;
|
||||
}
|
||||
|
||||
return new Proxy(
|
||||
{
|
||||
host: "",
|
||||
const urlprops = [
|
||||
"hash",
|
||||
"host",
|
||||
"hostname",
|
||||
"href",
|
||||
"origin",
|
||||
"pathname",
|
||||
"port",
|
||||
"search",
|
||||
];
|
||||
for (const prop of urlprops) {
|
||||
const native = nativeGetOwnPropertyDescriptor(self.location, prop);
|
||||
const desc = {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
get: new Proxy(native.get, {
|
||||
apply() {
|
||||
return client.url[prop];
|
||||
},
|
||||
{
|
||||
get(target, prop) {
|
||||
const loc = createLocation();
|
||||
|
||||
return loc[prop];
|
||||
}),
|
||||
};
|
||||
if (native.set) {
|
||||
desc.set = new Proxy(native.set, {
|
||||
apply(target, thisArg, args) {
|
||||
let url = new URL(client.url.href);
|
||||
url[prop] = args[0];
|
||||
self.location.href = encodeUrl(url.href);
|
||||
},
|
||||
|
||||
set(obj, prop, value) {
|
||||
const loc = createLocation();
|
||||
|
||||
if (prop === "href") {
|
||||
self.location.href = encodeUrl(value);
|
||||
} else {
|
||||
loc[prop] = value;
|
||||
});
|
||||
}
|
||||
Object.defineProperty(fakeLocation, prop, desc);
|
||||
}
|
||||
|
||||
return true;
|
||||
// functions
|
||||
fakeLocation.toString = new Proxy(self.location.toString, {
|
||||
apply() {
|
||||
return client.url.href;
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
fakeLocation.valueOf = new Proxy(self.location.valueOf, {
|
||||
apply() {
|
||||
return client.url.href;
|
||||
},
|
||||
});
|
||||
fakeLocation.assign = new Proxy(self.location.assign, {
|
||||
apply(target, thisArg, args) {
|
||||
args[0] = encodeUrl(args[0]);
|
||||
Reflect.apply(target, thisArg, args);
|
||||
},
|
||||
});
|
||||
fakeLocation.reload = new Proxy(self.location.reload, {
|
||||
apply(target, thisArg, args) {
|
||||
Reflect.apply(target, thisArg, args);
|
||||
},
|
||||
});
|
||||
fakeLocation.replace = new Proxy(self.location.replace, {
|
||||
apply(target, thisArg, args) {
|
||||
args[0] = encodeUrl(args[0]);
|
||||
Reflect.apply(target, thisArg, args);
|
||||
},
|
||||
});
|
||||
|
||||
return fakeLocation;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,3 @@
|
|||
export const nativeFunction = self.Function;
|
||||
export const nativeGetOwnPropertyDescriptor =
|
||||
self.Object.getOwnPropertyDescriptor;
|
||||
|
||||
// descriptors
|
||||
export const nativeDefaultViewGetter = nativeGetOwnPropertyDescriptor(
|
||||
Document.prototype,
|
||||
"defaultView"
|
||||
)!.get!;
|
||||
export const nativeContentDocumentGetter = nativeGetOwnPropertyDescriptor(
|
||||
HTMLIFrameElement.prototype,
|
||||
"contentDocument"
|
||||
)!.get!;
|
||||
export const nativeContentWindowGetter = nativeGetOwnPropertyDescriptor(
|
||||
HTMLIFrameElement.prototype,
|
||||
"contentWindow"
|
||||
)!.get!;
|
||||
|
|
|
@ -3,15 +3,11 @@ import { SCRAMJETCLIENT } from "../../symbols";
|
|||
import { ScramjetClient } from "../client";
|
||||
import { config } from "../shared";
|
||||
|
||||
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) {
|
||||
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);
|
||||
// argdbg(arg);
|
||||
}
|
||||
if (iswindow && identifier instanceof self.Window) {
|
||||
return client.globalProxy;
|
||||
|
@ -51,7 +47,15 @@ export default function (client: ScramjetClient, self: typeof globalThis) {
|
|||
}
|
||||
|
||||
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: client.wrapfn,
|
||||
writable: false,
|
||||
configurable: false,
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue