← All issues

[JSC][Temporal] Remove Temporal.Calendar object and update JS layer to Stage 4 spec

b35d67a

Temporal's Stage 3 design exposed Temporal.Calendar as a first-class JS constructor; Stage 4 dropped it in favor of embedded string calendar IDs. JSC goes further and replaces strings with a compact CalendarID integer enum, dispatching ICU calendar math through CalendarICUBridge at compile time. This integer now flows through every Temporal type boundary — parsers, constructors, with() methods, arithmetic operations — making conversion and validation at each boundary security-relevant.

Source/JavaScriptCore/runtime/TemporalCalendar.h

- class TemporalCalendar final : public JSNonFinalObject {
- String m_calendarId;
+ enum class CalendarID : uint8_t { ISO8601, Gregory, Japanese, /* ... */ };

The commit simultaneously fixes several spec-compliance bugs: PlainYearMonth rejects bare YYYY-MM without calendar annotation, PlainDateTime defaults missing time fields to 0 instead of undefined, PlainMonthDay.prototype.with() throws TypeError for unrecognised fields, PlainTime constructor rejects NaN.

Sweeping refactor that touches every calendar-aware Temporal type at its constructor, parser, and prototype boundary, with multiple simultaneous spec-compliance fixes signaling the previous code had latent incorrect behaviors.

The CalendarID integer enum now flows through every Temporal constructor and parser — check whether all string-to-enum conversions validate input before indexing the dispatch table, and whether an out-of-range CalendarID can propagate unchecked into CalendarICUBridge. The spec-compliance fixes are admissions the old code accepted invalid inputs; the same pattern (missing validation before arithmetic, undefined/NaN tolerance) may survive in untouched constructors or in with()/add()/subtract() prototype methods. PlainDateTime now defaults missing time fields to 0 — audit whether JS-side code that propagated undefined could trigger a different coercion path in the C++ layer. PlainMonthDay.prototype.with() now throws TypeError for unrecognised fields — check consistency with PlainDate.prototype.with() and PlainDateTime.prototype.with().