Compare commits

...

1 Commits

Author SHA1 Message Date
Claude Bot
106ef125c0 fix(resolver): allow long data URLs in module resolution
Data URLs can be very long (e.g. zip.js embeds ~25KB worker code in data URIs).
The path length check was rejecting these before they could be recognized as
data URLs. This fix excludes data URLs from the path length check.

Fixes #24161

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 22:10:57 +00:00
2 changed files with 85 additions and 1 deletions

View File

@@ -1743,7 +1743,9 @@ pub fn resolveMaybeNeedsTrailingSlash(
comptime is_a_file_path: bool,
is_user_require_resolve: bool,
) bun.JSError!void {
if (is_a_file_path and specifier.length() > comptime @as(u32, @intFromFloat(@trunc(@as(f64, @floatFromInt(bun.MAX_PATH_BYTES)) * 1.5)))) {
// Data URLs can be very long (e.g. zip.js embeds ~25KB worker code in data URIs),
// so don't apply the path length check to them.
if (is_a_file_path and (specifier.length() > comptime @as(u32, @intFromFloat(@trunc(@as(f64, @floatFromInt(bun.MAX_PATH_BYTES)) * 1.5)))) and !specifier.hasPrefixComptime("data:")) {
const specifier_utf8 = specifier.toUTF8(bun.default_allocator);
defer specifier_utf8.deinit();
const source_utf8 = source.toUTF8(bun.default_allocator);

View File

@@ -0,0 +1,82 @@
import { expect, test } from "bun:test";
// Test for issue #24161: Long data URLs in Web Workers should work
// zip.js embeds ~25KB worker code in data URIs, which was being rejected
// by the path length limit check before being recognized as data URLs.
test("Worker from a long data URL (>6KB)", async () => {
// Create a data URL that's longer than the MAX_PATH_BYTES * 1.5 (~6KB) limit
// by padding the worker code with a large comment
const padding = "a".repeat(10000); // 10KB of padding
const workerCode = `
/* ${padding} */
self.onmessage = e => {
self.postMessage(e.data + " processed");
};
`;
const dataUrl = `data:text/javascript,${encodeURIComponent(workerCode)}`;
// Verify our data URL is actually longer than the threshold
expect(dataUrl.length).toBeGreaterThan(6144);
const worker = new Worker(dataUrl);
const result = await new Promise((resolve, reject) => {
worker.onerror = e => reject(e.message);
worker.onmessage = e => {
worker.terminate();
resolve(e.data);
};
worker.postMessage("test");
});
expect(result).toBe("test processed");
});
test("Worker from a long base64 data URL", async () => {
// Create worker code and encode as base64
const padding = "a".repeat(10000);
const workerCode = `
/* ${padding} */
self.onmessage = e => {
self.postMessage(e.data + " base64");
};
`;
const base64Code = Buffer.from(workerCode).toString("base64");
const dataUrl = `data:text/javascript;base64,${base64Code}`;
// Verify our data URL is actually longer than the threshold
expect(dataUrl.length).toBeGreaterThan(6144);
const worker = new Worker(dataUrl);
const result = await new Promise((resolve, reject) => {
worker.onerror = e => reject(e.message);
worker.onmessage = e => {
worker.terminate();
resolve(e.data);
};
worker.postMessage("test");
});
expect(result).toBe("test base64");
});
test("Dynamic import of long data URL", async () => {
// Test that dynamic import of long data URLs also works
const padding = "a".repeat(10000);
const moduleCode = `
/* ${padding} */
export const value = "imported successfully";
`;
const dataUrl = `data:text/javascript,${encodeURIComponent(moduleCode)}`;
// Verify our data URL is actually longer than the threshold
expect(dataUrl.length).toBeGreaterThan(6144);
const module = await import(dataUrl);
expect(module.value).toBe("imported successfully");
});