Compare commits

...

1 Commits

Author SHA1 Message Date
Claude Bot
a6836bdbbf Add support for Blob and BunFile input to HTMLRewriter
HTMLRewriter.transform() now accepts Blob and BunFile objects directly,
in addition to Response, string, and ArrayBuffer inputs. This matches
the TypeScript type signature which already declared this support.

Previously, passing a Blob would throw "TypeError: Expected Response or Body".
Now the implementation properly handles Blob objects by converting them through
the Body.extract() path, which already has support for Blob inputs.

Tests added to verify both Blob and BunFile inputs work correctly.
2025-11-11 21:39:36 +00:00
2 changed files with 62 additions and 1 deletions

View File

@@ -186,12 +186,14 @@ pub const HTMLRewriter = struct {
return out;
}
const ResponseKind = enum { string, array_buffer, other };
const ResponseKind = enum { string, array_buffer, blob, other };
const kind: ResponseKind = brk: {
if (response_value.isString())
break :brk .string
else if (response_value.jsType().isTypedArrayOrArrayBuffer())
break :brk .array_buffer
else if (response_value.as(jsc.WebCore.Blob)) |_|
break :brk .blob
else
break :brk .other;
};
@@ -214,6 +216,12 @@ pub const HTMLRewriter = struct {
return global.throwValue(err);
}
out_response_value.ensureStillAlive();
// For blob input, return the Response directly
if (kind == .blob) {
return out_response_value;
}
var out_response = out_response_value.as(Response) orelse return out_response_value;
var blob = out_response.getBodyValue().useAsAnyBlobAllowNonUTF8String();
@@ -230,6 +238,7 @@ pub const HTMLRewriter = struct {
.array_buffer => brk: {
break :brk blob.toArrayBuffer(global, .transfer);
},
.blob => unreachable, // handled above
.other => unreachable,
};
}

View File

@@ -685,3 +685,55 @@ payloads.forEach(type => {
expect(calls).toBeGreaterThan(0);
});
});
// Test Blob input directly (without Response wrapper)
it("works with Blob input directly", async () => {
const htmlContent = '<script src="/main.js"></script>';
const blob = new Blob([htmlContent]);
let srcValue = null;
const result = new HTMLRewriter()
.on("script", {
element(element) {
srcValue = element.getAttribute("src");
},
})
.transform(blob);
expect(result).toBeInstanceOf(Response);
const text = await result.text();
expect(text).toBe(htmlContent);
expect(srcValue).toBe("/main.js");
});
// Test BunFile input
it("works with BunFile input", async () => {
const { mkdtemp, writeFile, rm } = await import("fs/promises");
const { tmpdir } = await import("os");
const { join } = await import("path");
const tempDir = await mkdtemp(join(tmpdir(), "htmlrewriter-test-"));
const tempFile = join(tempDir, "index.html");
const htmlContent = '<div id="test">Hello World</div>';
try {
await writeFile(tempFile, htmlContent);
const file = Bun.file(tempFile);
let divId = null;
const result = new HTMLRewriter()
.on("div", {
element(element) {
divId = element.getAttribute("id");
},
})
.transform(file);
expect(result).toBeInstanceOf(Response);
const text = await result.text();
expect(text).toBe(htmlContent);
expect(divId).toBe("test");
} finally {
await rm(tempDir, { recursive: true, force: true });
}
});