Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions scripts/build/deps/webkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
// oven-sh/WebKit main: macOS + Windows artifacts cross-compiled on Linux,
// -lto variants built with ThinLTO (per-module summaries for cross-language
// importing), every x64 at the nehalem floor (no separate -baseline variant),
// typed-array constructor ClassInfo kept address-unique under LTO, and the
// Windows ICU data table filtered + per-item zstd compressed.
export const WEBKIT_VERSION = "c9296e353e365ecf0de82f273bb0a88a3df465be";
// typed-array constructor ClassInfo kept address-unique under LTO, the
// Windows ICU data table filtered + per-item zstd compressed, and the eager
// timezone prewarm in VM::VM skipped under USE(BUN_JSC_ADDITIONS).
export const WEBKIT_VERSION = "9bded08f48f30b0fe37fdf5424a89b9bcae4349f";

/**
* WebKit (JavaScriptCore) — the JS engine.
Expand Down
42 changes: 41 additions & 1 deletion test/js/web/intl/intl.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// links the unmodified libicudata.a.

import { describe, expect, test } from "bun:test";
import { isLinux } from "harness";
import { bunEnv, bunExe, isLinux } from "harness";

// Snapshots are CLDR-version-specific. Only check them where Bun bundles the
// ICU they were generated against (Linux); macOS uses Apple's libicucore and
Expand Down Expand Up @@ -307,3 +307,43 @@
}
});
});

// The IANA timezone table and host-zone display-name cache are filled lazily on
// first Date / Intl access rather than inside VM::VM, so the first access can
// race across Workers that each construct their own VM. Exercise that race in a
// fresh process where nothing has warmed the cache yet: every Worker plus the
// main thread must observe the same resolved zone, the same supportedValuesOf
// count, and the same Date.prototype.toString output.
test.concurrent("timezone lazy-init is consistent across concurrent Workers", async () => {
const script = `
const probe = () => ({
zone: new Intl.DateTimeFormat().resolvedOptions().timeZone,
count: Intl.supportedValuesOf("timeZone").length,
date: new Date(0).toString(),
});
const body = "postMessage((" + probe.toString() + ")())";
const url = URL.createObjectURL(new Blob([body]));
const workers = Array.from({ length: 8 }, () => new Promise((resolve, reject) => {
const w = new Worker(url);
Comment thread
robobun marked this conversation as resolved.
w.onmessage = e => { resolve(e.data); w.terminate(); };
w.onerror = reject;
}));
Comment thread
robobun marked this conversation as resolved.
const results = [probe(), ...await Promise.all(workers)];

Check warning on line 331 in test/js/web/intl/intl.test.ts

View check run for this annotation

Claude / Claude Code Review

Main-thread probe() pre-warms the process-global timezone cache before Workers can race

In `[probe(), ...await Promise.all(workers)]`, array elements evaluate left-to-right, so `probe()` runs synchronously on the main thread's already-constructed VM *before* the `await` yields — while the 8 Workers are still spinning up threads and fresh VMs. The main thread therefore almost deterministically wins the process-global `std::call_once` for `initializeAvailableTimeZones`, so the Workers observe an already-filled cache instead of racing on cold init. Consider `const wr = await Promise.a
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
Comment thread
robobun marked this conversation as resolved.
Outdated
for (const r of results)
if (r.zone !== results[0].zone || r.count !== results[0].count || r.date !== results[0].date)
throw new Error("inconsistent: " + JSON.stringify(r) + " vs " + JSON.stringify(results[0]));
console.log(JSON.stringify(results[0]));
`;
await using proc = Bun.spawn({
cmd: [bunExe(), "-e", script],
env: { ...bunEnv, TZ: "America/New_York" },
stderr: "pipe",
});
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
expect(stderr).toBe("");
const result = JSON.parse(stdout.trim());
expect(result.zone).toBe("America/New_York");
expect(result.count).toBeGreaterThan(400);
expect(result.date).toContain("Eastern Standard Time");
Comment thread
robobun marked this conversation as resolved.
expect(exitCode).toBe(0);
});
Loading