File size: 3,042 Bytes
bee6636 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
import { ScramjetClient } from "./client";
import { nativeGetOwnPropertyDescriptor } from "./natives";
import { UrlChangeEvent } from "./events";
import { iswindow } from ".";
import { rewriteUrl } from "../shared/rewriters/url";
export function createLocationProxy(
client: ScramjetClient,
self: typeof globalThis
) {
const Location = iswindow ? self.Location : self.WorkerLocation;
// location cannot be Proxy()d
const fakeLocation: any = {};
Object.setPrototypeOf(fakeLocation, Location.prototype);
fakeLocation.constructor = Location;
// for some reason it's on the object for Location and on the prototype for WorkerLocation??
const descriptorSource = iswindow ? self.location : Location.prototype;
const urlprops = [
"protocol",
"hash",
"host",
"hostname",
"href",
"origin",
"pathname",
"port",
"search",
];
for (const prop of urlprops) {
const native = nativeGetOwnPropertyDescriptor(descriptorSource, prop);
if (!native) continue;
const desc: Partial<PropertyDescriptor> = {
configurable: true,
enumerable: true,
};
if (native.get) {
desc.get = new Proxy(native.get, {
apply() {
return client.url[prop];
},
});
}
if (native.set) {
desc.set = new Proxy(native.set, {
apply(target, that, args) {
if (prop === "href") {
// special case
client.url = args[0];
return;
}
if (prop === "hash") {
self.location.hash = args[0];
const ev = new UrlChangeEvent(client.url.href);
if (!client.isSubframe) client.frame?.dispatchEvent(ev);
return;
}
const url = new URL(client.url.href);
url[prop] = args[0];
client.url = url;
},
});
}
Object.defineProperty(fakeLocation, prop, desc);
}
// functions
fakeLocation.toString = new Proxy(self.location.toString, {
apply() {
return client.url.href;
},
});
if (self.location.valueOf)
fakeLocation.valueOf = new Proxy(self.location.valueOf, {
apply() {
return client.url.href;
},
});
if (self.location.assign)
fakeLocation.assign = new Proxy(self.location.assign, {
apply(target, that, args) {
args[0] = rewriteUrl(args[0], client.meta);
Reflect.apply(target, self.location, args);
const urlchangeev = new UrlChangeEvent(client.url.href);
if (!client.isSubframe) client.frame?.dispatchEvent(urlchangeev);
},
});
if (self.location.reload)
fakeLocation.reload = new Proxy(self.location.reload, {
apply(target, that, args) {
Reflect.apply(target, self.location, args);
},
});
if (self.location.replace)
fakeLocation.replace = new Proxy(self.location.replace, {
apply(target, that, args) {
args[0] = rewriteUrl(args[0], client.meta);
Reflect.apply(target, self.location, args);
const urlchangeev = new UrlChangeEvent(client.url.href);
if (!client.isSubframe) client.frame?.dispatchEvent(urlchangeev);
},
});
return fakeLocation;
}
|