Something went wrong. Try again.
Monorepo for Tangled
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133import { parseDiffFromFile, processPatch, type FileContents, type FileDiffMetadata} from "@pierre/diffs";
export interface DiffFileRequest { id: number; kind: "file"; oldFile: FileContents; newFile: FileContents;}
export interface DiffStreamRequest { id: number; kind: "stream"; /** transferred from the main thread, which is where the preload lives */ body?: ReadableStream<Uint8Array>; /** fallback for browsers that will not transfer a stream */ url?: string;}
export interface DiffCancelRequest { id: number; kind: "cancel";}
export type DiffWorkerRequest = DiffFileRequest | DiffStreamRequest | DiffCancelRequest;
export interface DiffWorkerResponse { id: number; fileDiff?: FileDiffMetadata; files?: FileDiffMetadata[]; /** a stream sends many responses; the last one carries done */ done?: boolean; error?: string;}
// Pierre's worker requires cacheKey to avoid warnings and cache syntax highlighting.const withCacheKeys = (files: FileDiffMetadata[]): FileDiffMetadata[] => { for (const file of files) file.cacheKey ??= `${file.prevObjectId ?? ""}:${file.newObjectId ?? ""}:${file.name}`; return files;};
const handle = (request: DiffFileRequest): DiffWorkerResponse => ({ id: request.id, fileDiff: parseDiffFromFile(request.oldFile, request.newFile)});
// Every file section in a git format-patch starts with FILE_MARK.const FILE_MARK = "\ndiff --git ";// enough files to be worth a message, few enough that the first ones paint while// the rest of a multi-megabyte body is still arrivingconst BATCH = 25;
// a page that navigated away is not owed the rest of its patchconst cancelled = new Set<number>();
const streamPatch = async (request: DiffStreamRequest): Promise<void> => { // a transferred body is already downloading: the document asked for it before // this worker existed. only fetch here when nothing was handed over const body = request.body ?? (await (async () => { if (!request.url) throw new Error("patch stream has neither body nor url"); const response = await fetch(request.url); if (!response.ok || !response.body) throw new Error(`patch ${response.status}`); return response.body; })());
const reader = body.getReader(); const decoder = new TextDecoder(); let buffer = ""; let batch: FileDiffMetadata[] = [];
const flush = (done: boolean) => { if (!done && batch.length === 0) return; self.postMessage({ id: request.id, files: batch, done } satisfies DiffWorkerResponse); batch = []; };
for (;;) { if (cancelled.has(request.id)) { cancelled.delete(request.id); await reader.cancel().catch(() => undefined); return; } const { value, done } = await reader.read(); if (value) buffer += decoder.decode(value, { stream: true }); // skip the mark at index 0: a section always opens with one for ( let mark = buffer.indexOf(FILE_MARK, 1); mark !== -1; mark = buffer.indexOf(FILE_MARK, 1) ) { const section = buffer.slice(0, mark + 1); buffer = buffer.slice(mark + 1); batch.push(...withCacheKeys(processPatch(section).files)); if (batch.length >= BATCH) flush(false); } if (done) break; }
buffer += decoder.decode(); if (buffer.trim()) batch.push(...withCacheKeys(processPatch(buffer).files)); flush(true);};
self.onmessage = (e: MessageEvent<DiffWorkerRequest>) => { const fail = (error: unknown) => self.postMessage({ id: e.data.id, done: true, error: error instanceof Error ? error.message : String(error) } satisfies DiffWorkerResponse);
try { if (e.data.kind === "cancel") { cancelled.add(e.data.id); return; } if (e.data.kind === "stream") { void streamPatch(e.data).catch(fail); return; } self.postMessage(handle(e.data) satisfies DiffWorkerResponse); } catch (error) { fail(error); }};