import { once } from "node:events"; import { createServer } from "node:http"; import { expect, it } from "vitest"; import { fetchWebSourceMaps } from "../../../src/browser/WebSourceMapFetcher.js"; import { analyzeWebBundleInputSchema, webSourceMapsSchema, } from "../../../src/domain/webBundleAnalysis.js"; import { WEB_SOURCE_MAP_LIMITS } from "../../../src/domain/webSourceLocation.js"; it.each([ { status: 300, followsRedirect: false }, { status: 304, followsRedirect: false }, { status: 305, followsRedirect: false }, { status: 306, followsRedirect: false }, { status: 301, followsRedirect: true }, { status: 302, followsRedirect: true }, { status: 303, followsRedirect: true }, { status: 307, followsRedirect: true }, { status: 308, followsRedirect: true }, ])( "follows HTTP $status with Location only when it is a redirect status", async ({ status, followsRedirect }) => { const calls: string[] = []; const server = createServer((request, response) => { const path = request.url ?? ""; calls.push(path); if (path === "/delivered.map") { response.writeHead(200, { "content-type": "application/json" }).end( JSON.stringify({ version: 3, names: [], sources: ["original.js"], mappings: "AAAA", }), ); return; } response.writeHead(status, { location: "/delivered.map" }).end(); }); try { const listening = once(server, "listening"); server.listen(0, "127.0.0.1"); await listening; const address = server.address(); if (address === null || typeof address === "string") throw new TypeError("Expected TCP listener"); const origin = `http://127.0.0.1:${String(address.port)}`; const input = analyzeWebBundleInputSchema.parse({ cdp_endpoint: "http://127.0.0.1:9222", target_id: "selected-page", allowed_origins: [origin], fetch_source_maps: true, }); const url = `${origin}/${String(status)}`; const result = await fetchWebSourceMaps( [ { scriptKey: `scr_${"1".repeat(64)}`, declaredUrl: url, fetchUrl: url, }, ], input, ); expect(calls).toEqual( followsRedirect ? [`/${String(status)}`, "/delivered.map"] : [`/${String(status)}`], ); expect(result.items[0]?.status).toBe( followsRedirect ? "included" : "fetch_failed", ); expect(result.items[0]).toMatchObject({ declared_url: url, effective_url: followsRedirect ? `${origin}/delivered.map` : url, }); if (!followsRedirect) expect(result.items[0]?.limitation).toBe( `Source-map server returned HTTP ${String(status)}.`, ); } finally { server.closeAllConnections(); if (server.listening) await new Promise((resolve, reject) => server.close((error) => error === undefined ? resolve() : reject(error), ), ); } }, ); it("keeps the declared URL and reports malformed redirect Location evidence", async () => { const declaredUrl = "https://app.example.test/declared.map"; const input = analyzeWebBundleInputSchema.parse({ cdp_endpoint: "http://127.0.0.1:9222", target_id: "selected-page", allowed_origins: ["https://app.example.test"], fetch_source_maps: true, }); const result = await fetchWebSourceMaps( [ { scriptKey: `scr_${"1".repeat(64)}`, declaredUrl, fetchUrl: declaredUrl, }, ], input, undefined, { fetch: () => Promise.resolve( new Response(null, { status: 302, headers: { location: "http://[invalid" }, }), ), }, ); expect(result.items[0]).toMatchObject({ status: "fetch_failed", declared_url: declaredUrl, effective_url: declaredUrl, limitation: expect.stringContaining("invalid Location URL"), }); expect(result.items[0]?.limitation).toContain(declaredUrl); expect(result.items[0]?.limitation).toContain("http://[invalid"); }); it.each(["invalid JSON", "invalid UTF-8", "HTTP failure", "response limit"])( "retains a redirected response URL for %s", async (failure) => { const origin = "https://app.example.test"; const declaredUrl = `${origin}/declared.map`; const fetchedUrl = `${origin}/maps/current.map?token=source-value#fragment`; const result = await fetchWebSourceMaps( [{ scriptKey: "script", declaredUrl, fetchUrl: declaredUrl }], analyzeWebBundleInputSchema.parse({ cdp_endpoint: "http://127.0.0.1:9222", target_id: "page", allowed_origins: [origin], fetch_source_maps: true, }), undefined, { ...(failure === "response limit" ? { maxResponseBytes: 1 } : {}), fetch: (url) => Promise.resolve( String(url) === declaredUrl ? new Response(null, { status: 302, headers: { location: fetchedUrl }, }) : new Response( failure === "invalid UTF-8" ? Uint8Array.from([0xff]) : "not-json", { status: failure === "HTTP failure" ? 503 : 200 }, ), ), }, ); expect(result.items[0]).toMatchObject({ declared_url: declaredUrl, effective_url: fetchedUrl, status: failure === "invalid JSON" || failure === "invalid UTF-8" ? "invalid" : "fetch_failed", artifact: null, }); const item = result.items[0]; if (item === undefined) throw new Error("Expected a fetched map result"); const legacyItem = { ...item }; delete legacyItem.effective_url; const legacy = webSourceMapsSchema.parse({ ...result, items: [legacyItem], }); expect(legacy.items[0]).not.toHaveProperty("effective_url"); }, ); it.each([ { cancellationFails: false, reason: null }, { cancellationFails: true, reason: new Error("fixture cancel failure") }, { cancellationFails: true, reason: undefined }, ])( "reserves a fetched URL before reading an over-cap response; cancellation failure=$cancellationFails, reason=$reason", async ({ cancellationFails, reason }) => { const origin = "https://app.example.test"; const fetchedUrl = `${origin}/${"u".repeat(WEB_SOURCE_MAP_LIMITS.outputBytes)}`; let cancelled = false; let read = false; const body = new ReadableStream( { pull(controller) { read = true; controller.enqueue( new TextEncoder().encode( '{"version":3,"sources":[],"names":[],"mappings":""}', ), ); controller.close(); }, cancel() { cancelled = true; if (cancellationFails) throw reason; }, }, { highWaterMark: 0 }, ); const pending = fetchWebSourceMaps( [ { scriptKey: "script", declaredUrl: `${origin}/declared.map`, fetchUrl: fetchedUrl, }, ], analyzeWebBundleInputSchema.parse({ cdp_endpoint: "http://127.0.0.1:9222", target_id: "page", allowed_origins: [origin], fetch_source_maps: true, }), undefined, { fetch: () => Promise.resolve(new Response(body)) }, ); if (cancellationFails) { await expect(pending).rejects.toMatchObject({ _tag: "AnalysisResourceConstraintError", message: expect.stringContaining("Expanded source-map evidence"), cleanupIncomplete: true, cleanupResources: ["source-map-response"], cause: expect.objectContaining({ errors: expect.arrayContaining([reason]), }), }); } else { await expect(pending).resolves.toMatchObject({ status: "unavailable", requested: 1, processed: 0, items: [], limitation: expect.stringContaining("1 requested map"), }); } expect(cancelled).toBe(true); expect(read).toBe(false); }, ); it("charges complete escaped redirect errors and cancels every discarded response", async () => { const origin = "https://app.example.test"; const location = `http://[${'\\"'.repeat(3_000)}`; const request = { scriptKey: "script", declaredUrl: `${origin}/map`, fetchUrl: `${origin}/map`, }; const input = analyzeWebBundleInputSchema.parse({ cdp_endpoint: "http://127.0.0.1:9222", target_id: "page", allowed_origins: [origin], fetch_source_maps: true, }); let calls = 0; let cancelled = 0; const host = { fetch: () => { calls += 1; return Promise.resolve( new Response( new ReadableStream({ cancel() { cancelled += 1; }, }), { status: 302, headers: { location } }, ), ); }, }; const control = await fetchWebSourceMaps([request], input, undefined, host); expect(control.items[0]?.limitation).toContain(JSON.stringify(location)); expect(control.items[0]?.limitation?.length).toBeGreaterThan(512); const result = await fetchWebSourceMaps( Array.from({ length: 1_500 }, () => request), input, undefined, host, ); expect(result).toMatchObject({ status: "unavailable", requested: 1_500 }); expect(result.processed).toBe(result.items.length); expect(result.processed).toBeLessThan(result.requested); expect(result.limitation).toContain("unknown"); expect(Buffer.byteLength(JSON.stringify(result))).toBeLessThanOrEqual( WEB_SOURCE_MAP_LIMITS.outputBytes, ); expect(calls).toBeLessThan(1_501); expect(cancelled).toBe(calls); });