70bf21e064
Deploy (to testing) and Test Playground Preview Worker / Deploy Playground Preview Worker (testing) (push) Has been skipped
Deploy Workers Shared Staging / Deploy Workers Shared Staging (push) Failing after 0s
Prerelease / build (push) Has been skipped
Handle Changesets / Handle Changesets (push) Has been cancelled
Semgrep OSS scan / semgrep-oss (push) Has been cancelled
112 lines
3.6 KiB
TypeScript
112 lines
3.6 KiB
TypeScript
import { useCallback } from "react";
|
|
import { Channel } from "./ipc";
|
|
import type { FromErrorPage, SourcesLoadedMessage, ToErrorPage } from "./ipc";
|
|
import type { TypedModule } from "./types";
|
|
|
|
const encoder = new TextEncoder();
|
|
const decoder = new TextDecoder();
|
|
|
|
function getFilesFromModules(
|
|
entrypoint: string,
|
|
modules: Record<string, TypedModule>,
|
|
serviceWorkerScript: string | undefined
|
|
) {
|
|
const isServiceWorker =
|
|
Object.entries(modules).length === 1 && serviceWorkerScript !== undefined;
|
|
|
|
const files = isServiceWorker
|
|
? [
|
|
{
|
|
path: entrypoint,
|
|
contents: encoder.encode(serviceWorkerScript),
|
|
},
|
|
]
|
|
: Object.entries(modules)
|
|
.filter(
|
|
([path, m]) =>
|
|
path.endsWith(".js") ||
|
|
m.type === "application/javascript" ||
|
|
m.type === "application/javascript+module"
|
|
)
|
|
.map(([path, m]) => ({
|
|
path,
|
|
contents: m.contents,
|
|
}));
|
|
|
|
let internalLines: number | undefined;
|
|
if (isServiceWorker && modules[entrypoint]) {
|
|
const totalScriptLength = serviceWorkerScript?.split("\n").length ?? 0;
|
|
|
|
const userScriptLength = decoder
|
|
.decode(modules[entrypoint].contents)
|
|
.split("\n").length;
|
|
|
|
internalLines = totalScriptLength - userScriptLength;
|
|
}
|
|
|
|
return { files, internalLines };
|
|
}
|
|
|
|
/**
|
|
* This hook works in tandem with the format-errors worker
|
|
* See https://github.com/cloudflare/workers-sdk/tree/main/packages/format-errors/README.md
|
|
*
|
|
* When given a Worker's source, which has:
|
|
* - `entrypoint` & `modules` for a modules-syntax Worker
|
|
* - `entrypoint`, `modules` & `serviceWorkerScript` for a service-worker syntax Worker
|
|
* In this context, `serviceWorkerScript` is the contents of the entrypoint module with
|
|
* potentially some additional lines of code prepended. The calculated `internalLines` number
|
|
* represents how many internal lines of code have been prepended, and should be stripped
|
|
* before displaying to the user. The prepended lines of code can be arbitrary, but in our context
|
|
* usually represent the middleware system: https://github.com/cloudflare/workers-sdk/tree/main/packages/wrangler/templates/middleware/loader-sw.ts
|
|
*
|
|
* this hook will return a callback that can be used to respond to the `load` event of
|
|
* an iframe which renders the `format-errors` worker. It will construct the `MessageChannel`
|
|
* & `MessagePort`s appropriately to construct the right messages for inflating the `format-errors`
|
|
* stack traces: https://github.com/cloudflare/workers-sdk/tree/main/packages/format-errors/README.md#L28
|
|
*/
|
|
export function useInjectSources(
|
|
entrypoint: string | undefined,
|
|
modules: Record<string, TypedModule> | undefined,
|
|
serviceWorkerScript?: string
|
|
): (frame: HTMLIFrameElement) => void {
|
|
return useCallback(
|
|
(frame) => {
|
|
// Create a new channel on every load, since they'll be sent to the iframe and can't be used on the next load.
|
|
const errorPage = Channel<ToErrorPage, FromErrorPage>(
|
|
new MessageChannel()
|
|
);
|
|
try {
|
|
frame.contentWindow?.postMessage("PORT", "*", [errorPage.remote]);
|
|
} catch (e) {
|
|
console.error("new load", e);
|
|
}
|
|
|
|
errorPage.onMessage((data) => {
|
|
if (!entrypoint || !modules) {
|
|
return;
|
|
}
|
|
if (data.type === "RequestSources") {
|
|
const { files, internalLines } = getFilesFromModules(
|
|
entrypoint,
|
|
modules,
|
|
serviceWorkerScript
|
|
);
|
|
|
|
const message: SourcesLoadedMessage = {
|
|
type: "SourcesLoaded",
|
|
body: {
|
|
name: "worker",
|
|
entrypoint,
|
|
files,
|
|
internalLines: internalLines ?? 0,
|
|
},
|
|
};
|
|
errorPage.postMessage(message);
|
|
}
|
|
});
|
|
},
|
|
[entrypoint, modules, serviceWorkerScript]
|
|
);
|
|
}
|