fix postmessage shit

This commit is contained in:
velzie 2024-08-02 22:44:16 -04:00
parent 6cccf1f412
commit d011d73a80
No known key found for this signature in database
GPG key ID: 048413F95F0DDE1F
6 changed files with 44 additions and 36 deletions

View file

@ -46,7 +46,7 @@ export class ScramjetClient {
windowProxy: any;
locationProxy: any;
eventcallbacks: WeakMap<
eventcallbacks: Map<
any,
[
{
@ -55,7 +55,7 @@ export class ScramjetClient {
proxiedCallback: AnyFunction;
},
]
> = new WeakMap();
> = new Map();
constructor(public global: typeof globalThis) {
if ("document" in self) {

View file

@ -1,5 +1,6 @@
import { encodeUrl } from "../shared";
import { ScramjetClient } from "../client";
import { type MessageC2W } from "../../worker";
// we need a late order because we're mangling with addEventListener at a higher level
export const order = 2;
@ -47,7 +48,8 @@ export default function (client: ScramjetClient, self: Self) {
{
scramjet$type: "registerServiceWorker",
port: handle,
},
origin: client.url.origin,
} as MessageC2W,
[handle]
);

View file

@ -15,7 +15,9 @@ if (!(ScramjetClient.SCRAMJET in self)) {
const client = new ScramjetClient(self);
client.hook();
if (issw) {
if (
new URL(self.location.href).searchParams.get("dest") === "serviceworker"
) {
const runtime = new ScramjetServiceWorkerRuntime(client);
runtime.hook();
}

View file

@ -3,32 +3,30 @@ import { encodeUrl } from "./shared";
export class ScramjetServiceWorkerRuntime {
constructor(public client: ScramjetClient) {
addEventListener("connect", (cevent: MessageEvent) => {
// @ts-ignore
self.onconnect = (cevent: MessageEvent) => {
const port = cevent.ports[0];
port.addEventListener("message", (event) => {
if ("scramjet$type" in event.data) {
handleMessage(client, event.data, port);
handleMessage(client, event.data);
}
});
port.start();
});
};
}
hook() {}
}
function handleMessage(
client: ScramjetClient,
data: MessageW2R,
port: MessagePort
) {
function handleMessage(client: ScramjetClient, data: MessageW2R) {
const port = data.scramjet$port;
const type = data.scramjet$type;
const token = data.scramjet$token;
if (type === "fetch") {
const fetchhandlers = client.eventcallbacks.get("fetch");
const fetchhandlers = client.eventcallbacks.get(self);
if (!fetchhandlers) return;
for (const handler of fetchhandlers) {
@ -37,24 +35,21 @@ function handleMessage(
body: request.body,
headers: new Headers(request.headers),
method: request.method,
mode: request.mode,
mode: "same-origin",
});
Object.defineProperty(fakeRequest, "destination", {
value: request.destinitation,
});
const fakeFetchEvent = new FetchEvent("fetch", {
request: fakeRequest,
});
// TODO: clean up, maybe put into a class
const fakeFetchEvent: any = new Event("fetch");
fakeFetchEvent.request = fakeRequest;
fakeFetchEvent.respondWith = async (
response: Response | Promise<Response>
) => {
response = await response;
response.body;
port.postMessage({
const message: MessageR2W = {
scramjet$type: "fetch",
scramjet$token: token,
scramjet$response: {
@ -63,7 +58,9 @@ function handleMessage(
status: response.status,
statusText: response.statusText,
},
} as MessageR2W);
};
port.postMessage(message, [response.body]);
};
handler.proxiedCallback(trustEvent(fakeFetchEvent));
@ -76,7 +73,7 @@ function trustEvent(event: Event): Event {
get(target, prop, reciever) {
if (prop === "isTrusted") return true;
return Reflect.get(target, prop, reciever);
return Reflect.get(target, prop);
},
});
}
@ -118,4 +115,5 @@ type MessageCommon = {
};
export type MessageR2W = MessageCommon & MessageTypeR2W;
export type MessageW2R = MessageCommon & MessageTypeW2R;
export type MessageW2R = MessageCommon &
MessageTypeW2R & { scramjet$port: MessagePort };

View file

@ -3,18 +3,18 @@ import { type MessageW2R, type MessageR2W } from "../client/swruntime";
export class FakeServiceWorker {
syncToken = 0;
promises: Record<number, (val?: MessageR2W) => void> = {};
messageChannel = new MessageChannel();
constructor(
public handle: MessagePort,
public origin: string
) {
this.handle.start();
this.handle.addEventListener("message", (event) => {
this.messageChannel.port1.addEventListener("message", (event) => {
if ("scramjet$type" in event.data) {
this.handleMessage(event.data);
}
});
this.messageChannel.port1.start();
}
handleMessage(data: MessageR2W) {
@ -31,6 +31,7 @@ export class FakeServiceWorker {
const message: MessageW2R = {
scramjet$type: "fetch",
scramjet$token: token,
scramjet$port: this.messageChannel.port2,
scramjet$request: {
url: request.url,
body: request.body,
@ -41,7 +42,10 @@ export class FakeServiceWorker {
},
};
this.handle.postMessage(message);
const transfer: any = request.body ? [request.body] : [];
transfer.push(this.messageChannel.port2);
this.handle.postMessage(message, transfer);
const { scramjet$response: r } = (await new Promise((resolve) => {
this.promises[token] = resolve;

View file

@ -3,6 +3,7 @@ import IDBMap from "@webreflection/idb-map";
import { ParseResultType } from "parse-domain";
import { ScramjetServiceWorker } from ".";
import { renderError } from "./error";
import { FakeServiceWorker } from "./fakesw";
const { encodeUrl, decodeUrl } = self.$scramjet.shared.url;
const { rewriteHeaders, rewriteHtml, rewriteJs, rewriteCss, rewriteWorkers } =
@ -35,14 +36,6 @@ export async function swfetch(
});
}
const activeWorker = this.serviceWorkers.find(
(w) => w.origin === new URL(request.url).origin
);
if (activeWorker) {
// TODO: check scope
return await activeWorker.fetch(request);
}
const urlParam = new URLSearchParams(new URL(request.url).search);
if (urlParam.has("url")) {
@ -53,6 +46,15 @@ export async function swfetch(
try {
const url = new URL(decodeUrl(request.url));
const activeWorker: FakeServiceWorker | null = this.serviceWorkers.find(
(w) => w.origin === url.origin
);
if (activeWorker) {
// TODO: check scope
return await activeWorker.fetch(request);
}
if (url.origin == new URL(request.url).origin) {
throw new Error(
"attempted to fetch from same origin - this means the site has obtained a reference to the real origin, aborting"