Skip to content

fix(runtime): #5582 — coerce null Intl option values per GetOption (10 test262)#5729

Merged
proggeramlug merged 1 commit into
mainfrom
worktree-fix-5582-datetimeformat
Jun 27, 2026
Merged

fix(runtime): #5582 — coerce null Intl option values per GetOption (10 test262)#5729
proggeramlug merged 1 commit into
mainfrom
worktree-fix-5582-datetimeformat

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Addresses part of #5582 (test262 intl402 DateTimeFormat parity). ECMA-402 GetOption treats only undefined as "absent → use the fallback"; every other value — null included — is coerced with ToString and then validated. Perry's get_option_string short-circuited null to None, so a null enum option was silently ignored instead of being rejected.

With this fix null coerces to the string "null", which:

  • fails every closed-enum allow-list → RangeError (matching Node), for localeMatcher, formatMatcher, weekday, hourCycle, dateStyle, and the NumberFormat / ListFormat / RelativeTimeFormat enums (style, type, numeric, currencyDisplay, roundingPriority, …); and
  • for the Unicode locale-extension keys calendar / numberingSystem, "null" is a well-formed but unsupported type subtag, so ResolveLocale drops it and resolvedOptions reports the locale default (gregory / latn). A small get_locale_extension_option mirrors that observable outcome by treating null as absent rather than echoing "null". It reads the option getter exactly once so the GetOption call-order tests still pass.

Validation

Local test262 sweep (pinned sha 4249661, Node v26.3.0 oracle, scripts/test262_subset.py) across intl402/{DateTimeFormat,NumberFormat,ListFormat,PluralRules,RelativeTimeFormat,Locale}:

+10 pass, 0 regressions (321 → 311 runtime-fails).

Fixed:

DateTimeFormat/test-option-date-time-components.js
DateTimeFormat/test-option-formatMatcher.js
DateTimeFormat/test-option-localeMatcher.js
ListFormat/constructor/constructor/options-style-invalid.js
ListFormat/constructor/constructor/options-type-invalid.js
NumberFormat/test-option-currencyDisplay.js
NumberFormat/test-option-roundingPriority.js
NumberFormat/test-option-style.js
RelativeTimeFormat/constructor/constructor/options-numeric-invalid.js
RelativeTimeFormat/constructor/constructor/options-style-invalid.js

Added gap test test-files/test_gap_intl_datetimeformat_null_option_5582.ts, which is byte-identical against node --experimental-strip-types.

Note: the remaining #5582 failures are largely Temporal/ICU formatting-fidelity gaps — Perry's DateTimeFormat format/formatToParts currently render a fixed M/D/YYYY regardless of component/style/timeZone options. That formatting overhaul is out of scope here.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved Intl.DateTimeFormat handling for null option values.
    • null is now treated as absent for calendar and numberingSystem, preventing errors and allowing locale-based fallback.
    • Other format options keep their existing validation behavior, with null still handled consistently.

…(10 test262)

ECMA-402 GetOption treats only `undefined` as "absent → use fallback"; every
other value, `null` included, is coerced with ToString and validated. Perry's
`get_option_string` short-circuited `null` to `None`, so a `null` enum option
(localeMatcher, formatMatcher, weekday, hourCycle, dateStyle, style, type,
numeric, currencyDisplay, roundingPriority, …) was silently ignored instead of
surfacing as the string "null", failing the allow-list, and raising a RangeError.

Now `null` coerces to "null" like any other ToString-able value. For the Unicode
locale-extension keys (`calendar`, `numberingSystem`) "null" is a well-formed
but unsupported `type` subtag, so ResolveLocale drops it and resolvedOptions
reports the locale default — a new `get_locale_extension_option` mirrors that
observable outcome by treating `null` as absent rather than echoing "null".
The property getter is read exactly once so the GetOption call-order tests
(constructor-calendar-numberingSystem-order.js) still pass.

Net test262 intl402 (DateTimeFormat/NumberFormat/ListFormat/PluralRules/
RelativeTimeFormat/Locale): +10 pass, 0 regressions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a714c989-594c-4d13-a505-4f6a8c818eff

📥 Commits

Reviewing files that changed from the base of the PR and between f8c259c and bd71f2b.

📒 Files selected for processing (2)
  • crates/perry-runtime/src/intl.rs
  • test-files/test_gap_intl_datetimeformat_null_option_5582.ts

📝 Walkthrough

Walkthrough

Intl option coercion now distinguishes undefined from null, and DateTimeFormat treats calendar and numberingSystem as locale-extension options with null-as-absent behavior. A new test exercises null inputs and the resulting resolvedOptions() values.

Changes

Intl DateTimeFormat null option handling

Layer / File(s) Summary
Shared option coercion
crates/perry-runtime/src/intl.rs
Adds coerce_option_string, rebuilds get_option_string on it, and adds get_locale_extension_option with different null handling for Unicode locale-extension keys.
DateTimeFormat null handling and test
crates/perry-runtime/src/intl.rs, test-files/test_gap_intl_datetimeformat_null_option_5582.ts
DateTimeFormat reads calendar and numberingSystem through get_locale_extension_option, and the new test probes null behavior for several option names plus locale-extension resolution.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • PerryTS/perry#5601: Also changes crates/perry-runtime/src/intl.rs Intl.DateTimeFormat option handling around calendar and related locale-extension behavior.
  • PerryTS/perry#5649: Also changes Intl.DateTimeFormat option parsing in make_instance, including numberingSystem and null-related semantics.

Poem

A bunny hopped through Intl’s gate,
With null and undef in different state.
calendar blinked, numberingSystem too,
The locale keys knew what to do.
نرم hops and whiskers, all agreed:
absent means absent—just what we need. 🐰

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers summary and validation, but it omits required template sections like Changes, Related issue, Test plan, and Checklist. Add the missing template sections: concrete Changes bullets, Related issue, explicit Test plan commands, optional screenshots/output, and the checklist items.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main runtime change around coercing null Intl option values.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-fix-5582-datetimeformat

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@proggeramlug proggeramlug merged commit cefad7a into main Jun 27, 2026
15 checks passed
@proggeramlug proggeramlug deleted the worktree-fix-5582-datetimeformat branch June 27, 2026 08:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant