diff --git a/scripts/build/deps/webkit.ts b/scripts/build/deps/webkit.ts index 7e8ddecce2ac..ed799d872e1d 100644 --- a/scripts/build/deps/webkit.ts +++ b/scripts/build/deps/webkit.ts @@ -3,7 +3,7 @@ * for local mode. Override via `--webkit-version=` to test a branch. * From https://github.com/oven-sh/WebKit releases. */ -export const WEBKIT_VERSION = "2e2aa2290fac856d6f451ceacb58f7f5b44dd057"; +export const WEBKIT_VERSION = "autobuild-preview-pr-600-cbbbe00e"; /** * WebKit (JavaScriptCore) — the JS engine. diff --git a/test/js/web/temporal/temporal.test.ts b/test/js/web/temporal/temporal.test.ts index d2d1deb7044a..401d0f3bd8ee 100644 --- a/test/js/web/temporal/temporal.test.ts +++ b/test/js/web/temporal/temporal.test.ts @@ -86,3 +86,86 @@ describe("Temporal core operations", () => { expect(() => structuredClone(Temporal.Instant.from("2024-06-15T00:00Z"))).toThrow(DOMException); }); }); + +// Divergences from V8 found by differential fuzzing. Expected values are what Node 26 / Chromium 148 print. +describe("Temporal spec conformance", () => { + // ToTemporalDate: PrepareCalendarFields, then GetOptionsObject (TypeError), then CalendarDateFromFields + // (era resolution and the ISODateWithinLimits check, both RangeError). + describe("PlainDate.from rejects a non-object options before it resolves the calendar fields", () => { + test.each([ + [{ year: -271821, month: 2, day: 31 }, RangeError], + [{ year: 275760, month: 9, day: 14 }, RangeError], + [{ era: "xx", eraYear: 1, month: 1, day: 1, calendar: "gregory" }, RangeError], + [{ year: 2024, month: 13, day: 1 }, "2024-12-01"], + ] as const)("%j", (bag, withValidOptions) => { + for (const options of [null, "constrain", 1, true]) { + expect(() => Temporal.PlainDate.from(bag, options as any)).toThrow(TypeError); + } + // With a real options object the late RangeError (or the constrained date) surfaces. + if (typeof withValidOptions === "string") { + expect(Temporal.PlainDate.from(bag, {}).toString()).toBe(withValidOptions); + } else { + expect(() => Temporal.PlainDate.from(bag, {})).toThrow(withValidOptions); + } + }); + + test("the bag is read first, and PrepareCalendarFields errors still win", () => { + const reads: PropertyKey[] = []; + const bag = new Proxy( + { year: -271821, month: 2, day: 31 }, + { get: (t, k, r) => (reads.push(k), Reflect.get(t, k, r)) }, + ); + expect(() => Temporal.PlainDate.from(bag, null as any)).toThrow(TypeError); + expect(reads).toEqual(["calendar", "day", "month", "monthCode", "year"]); + expect(() => Temporal.PlainDate.from({ year: 2024, month: 0, day: 1 }, null as any)).toThrow(RangeError); + }); + }); + + test("rounding to weeks accepts a window edge on the minimum PlainDate", () => { + const later = Temporal.PlainDate.from("2016-02-29"); + const nearMin = Temporal.PlainDate.from("-271821-04-20"); + const results = Object.fromEntries( + ["trunc", "floor", "expand", "halfExpand"].map(roundingMode => [ + roundingMode, + later.since(nearMin, { smallestUnit: "weeks", roundingMode: roundingMode as Temporal.RoundingMode }).toString(), + ]), + ); + expect(results).toEqual({ + trunc: "P14288122W", + floor: "P14288122W", + expand: "P14288123W", + halfExpand: "P14288123W", + }); + expect(nearMin.until(later, { smallestUnit: "weeks" }).toString()).toBe("P14288122W"); + expect(later.since(nearMin, { smallestUnit: "days", roundingIncrement: 7 }).toString()).toBe("P100016854D"); + expect( + Temporal.Duration.from({ days: -100016860 }) + .round({ relativeTo: later, smallestUnit: "weeks", roundingMode: "trunc" }) + .toString(), + ).toBe("-P14288122W"); + // An edge that is really below the minimum still throws (here: the exact minimum as operand). + expect(() => later.since("-271821-04-19", { smallestUnit: "weeks" })).toThrow(RangeError); + }); + + describe("era codes match the lowercase CLDR identifiers exactly", () => { + test.each([ + ["gregory", "CE"], + ["gregory", "Bce"], + ["gregory", "AD"], + ["japanese", "Reiwa"], + ["hebrew", "AM"], + ])("%s rejects %s", (calendar, era) => { + expect(() => Temporal.PlainDate.from({ era, eraYear: 1, month: 1, day: 1, calendar })).toThrow(RangeError); + }); + + test("lowercase codes and aliases resolve", () => { + expect(Temporal.PlainDate.from({ era: "ce", eraYear: 1, month: 1, day: 1, calendar: "gregory" }).toString()).toBe( + "0001-01-01[u-ca=gregory]", + ); + expect(Temporal.PlainDate.from({ era: "ad", eraYear: 1, month: 1, day: 1, calendar: "gregory" }).era).toBe("ce"); + expect( + Temporal.PlainDate.from({ era: "reiwa", eraYear: 1, month: 5, day: 1, calendar: "japanese" }).toString(), + ).toBe("2019-05-01[u-ca=japanese]"); + }); + }); +});