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

View file

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

View file

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

View file

@ -3,32 +3,30 @@ import { encodeUrl } from "./shared";
export class ScramjetServiceWorkerRuntime { export class ScramjetServiceWorkerRuntime {
constructor(public client: ScramjetClient) { constructor(public client: ScramjetClient) {
addEventListener("connect", (cevent: MessageEvent) => { // @ts-ignore
self.onconnect = (cevent: MessageEvent) => {
const port = cevent.ports[0]; const port = cevent.ports[0];
port.addEventListener("message", (event) => { port.addEventListener("message", (event) => {
if ("scramjet$type" in event.data) { if ("scramjet$type" in event.data) {
handleMessage(client, event.data, port); handleMessage(client, event.data);
} }
}); });
port.start(); port.start();
}); };
} }
hook() {} hook() {}
} }
function handleMessage( function handleMessage(client: ScramjetClient, data: MessageW2R) {
client: ScramjetClient, const port = data.scramjet$port;
data: MessageW2R,
port: MessagePort
) {
const type = data.scramjet$type; const type = data.scramjet$type;
const token = data.scramjet$token; const token = data.scramjet$token;
if (type === "fetch") { if (type === "fetch") {
const fetchhandlers = client.eventcallbacks.get("fetch"); const fetchhandlers = client.eventcallbacks.get(self);
if (!fetchhandlers) return; if (!fetchhandlers) return;
for (const handler of fetchhandlers) { for (const handler of fetchhandlers) {
@ -37,24 +35,21 @@ function handleMessage(
body: request.body, body: request.body,
headers: new Headers(request.headers), headers: new Headers(request.headers),
method: request.method, method: request.method,
mode: request.mode, mode: "same-origin",
}); });
Object.defineProperty(fakeRequest, "destination", { Object.defineProperty(fakeRequest, "destination", {
value: request.destinitation, value: request.destinitation,
}); });
const fakeFetchEvent = new FetchEvent("fetch", { // TODO: clean up, maybe put into a class
request: fakeRequest, const fakeFetchEvent: any = new Event("fetch");
}); fakeFetchEvent.request = fakeRequest;
fakeFetchEvent.respondWith = async ( fakeFetchEvent.respondWith = async (
response: Response | Promise<Response> response: Response | Promise<Response>
) => { ) => {
response = await response; response = await response;
const message: MessageR2W = {
response.body;
port.postMessage({
scramjet$type: "fetch", scramjet$type: "fetch",
scramjet$token: token, scramjet$token: token,
scramjet$response: { scramjet$response: {
@ -63,7 +58,9 @@ function handleMessage(
status: response.status, status: response.status,
statusText: response.statusText, statusText: response.statusText,
}, },
} as MessageR2W); };
port.postMessage(message, [response.body]);
}; };
handler.proxiedCallback(trustEvent(fakeFetchEvent)); handler.proxiedCallback(trustEvent(fakeFetchEvent));
@ -76,7 +73,7 @@ function trustEvent(event: Event): Event {
get(target, prop, reciever) { get(target, prop, reciever) {
if (prop === "isTrusted") return true; 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 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 { export class FakeServiceWorker {
syncToken = 0; syncToken = 0;
promises: Record<number, (val?: MessageR2W) => void> = {}; promises: Record<number, (val?: MessageR2W) => void> = {};
messageChannel = new MessageChannel();
constructor( constructor(
public handle: MessagePort, public handle: MessagePort,
public origin: string public origin: string
) { ) {
this.handle.start(); this.messageChannel.port1.addEventListener("message", (event) => {
this.handle.addEventListener("message", (event) => {
if ("scramjet$type" in event.data) { if ("scramjet$type" in event.data) {
this.handleMessage(event.data); this.handleMessage(event.data);
} }
}); });
this.messageChannel.port1.start();
} }
handleMessage(data: MessageR2W) { handleMessage(data: MessageR2W) {
@ -31,6 +31,7 @@ export class FakeServiceWorker {
const message: MessageW2R = { const message: MessageW2R = {
scramjet$type: "fetch", scramjet$type: "fetch",
scramjet$token: token, scramjet$token: token,
scramjet$port: this.messageChannel.port2,
scramjet$request: { scramjet$request: {
url: request.url, url: request.url,
body: request.body, 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) => { const { scramjet$response: r } = (await new Promise((resolve) => {
this.promises[token] = resolve; this.promises[token] = resolve;

View file

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