Skip to content

Commit

Permalink
BrowserServer fixes for ServiceWorker
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-nagy committed Dec 30, 2023
1 parent da95ae2 commit fcce2f2
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 17 deletions.
4 changes: 2 additions & 2 deletions packages/browser/src/BrowserClient.sw.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ afterEach(async () => {
});

test("a frame making a request to a service worker", async () => {
const [worker] = await Test.createServiceWorker(/* ts */ `
await Test.createServiceWorker(/* ts */ `
import * as BrowserServer from "http://localhost:8000/packages/browser/src/BrowserServer.ts";
const server = BrowserServer.listen({
Expand All @@ -24,7 +24,7 @@ test("a frame making a request to a service worker", async () => {
});
`);

const client = BrowserClient.from(worker);
const client = BrowserClient.from(BrowserClient.SW);
const response = await client.fetch();

assert.match(response, "hi from the worker");
Expand Down
32 changes: 17 additions & 15 deletions packages/browser/src/BrowserClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ export type Options = {
origin?: string;
};

/**
* An atom that symbolizes a ServiceWorker. When used as a target the client
* will make requests to the currently active ServiceWorker.
*/
export const SW = Symbol.for("ServiceWorker");

export type SW = typeof SW;

export class BrowserClient {
/**
* The address of the server. An address is like a port number, except an
Expand All @@ -37,7 +45,7 @@ export class BrowserClient {
/**
* The message target. A message target is like a server host.
*/
public readonly target: Window | Worker | SharedWorker | ServiceWorker;
public readonly target: Window | Worker | SharedWorker | SW;

constructor({
address = "",
Expand All @@ -46,7 +54,7 @@ export class BrowserClient {
}: {
address?: string;
origin?: string;
target: Window | Worker | SharedWorker | ServiceWorker;
target: Window | Worker | SharedWorker | SW;
}) {
this.serverAddress = address;
this.origin = origin;
Expand All @@ -58,7 +66,7 @@ export class BrowserClient {
* response from the server.
*/
async fetch(body: StructuredCloneable.t): Promise<StructuredCloneable.t> {
const messageSink = getMessageSink(this.target);
const messageSink = await getMessageSink(this.target);
const messageSource = getMessageSource(this.target);
const request = Request.t({ address: this.serverAddress, body });

Expand All @@ -73,10 +81,6 @@ export class BrowserClient {
Observable.map((message) => message.data.body)
);

// Not sure it this is necessary or useful.
if (this.target instanceof ServiceWorker)
await navigator.serviceWorker.ready;

messageSink.postMessage(request, { targetOrigin: this.origin });

return Observable.firstValueFrom(response);
Expand All @@ -94,29 +98,27 @@ export class BrowserClient {
* const response = await client.fetch("👋");
*/
export function from(
target: Window | Worker | SharedWorker | ServiceWorker,
target: Window | Worker | SharedWorker | SW,
options: Options = {}
) {
if (target instanceof SharedWorker) target.port.start();
return new BrowserClient({ ...options, target });
}

function getMessageSink(
target: Window | Worker | SharedWorker | ServiceWorker
) {
function getMessageSink(target: Window | Worker | SharedWorker | SW) {
switch (true) {
case target === SW:
return navigator.serviceWorker.ready.then((r) => r.active!);
case target instanceof SharedWorker:
return target.port;
default:
return target;
}
}

function getMessageSource(
target: Window | Worker | SharedWorker | ServiceWorker
) {
function getMessageSource(target: Window | Worker | SharedWorker | SW) {
switch (true) {
case target instanceof ServiceWorker:
case target === SW:
return navigator.serviceWorker;
case target instanceof SharedWorker:
return target.port;
Expand Down

0 comments on commit fcce2f2

Please sign in to comment.