Skip to content

feat(intl): implement Date.prototype.toLocaleString, toLocaleDateString, and toLocaleTimeString#5080

Merged
nekevss merged 5 commits intoboa-dev:mainfrom
alienx5499:feat/5075-date-tolocalestring
Mar 19, 2026
Merged

feat(intl): implement Date.prototype.toLocaleString, toLocaleDateString, and toLocaleTimeString#5080
nekevss merged 5 commits intoboa-dev:mainfrom
alienx5499:feat/5075-date-tolocalestring

Conversation

@alienx5499
Copy link
Contributor

This Pull Request fixes/closes #5075.

It changes the following:

  • Implement Date.prototype.toLocaleString, toLocaleDateString, and toLocaleTimeString using Intl.DateTimeFormat when the intl feature is enabled (ECMA-402 20.4.1–20.4.3).
  • Add shared helper format_date_time_locale in intl/date_time_format; expose create_date_time_format as pub(crate); add FormatDefaults::All and fix default-application logic for it.
  • Add this_date_value helper for the RequireInternalSlot / [[DateValue]] step in the three methods.
  • Return "Invalid Date" for NaN in all three methods; when intl is disabled, fall back to Date.prototype.toString.
  • Add #[cfg(feature = "intl")] tests: invalid receiver (TypeError), NaN → "Invalid Date", typeof checks, locale differences (en-US vs de-DE) for all three methods, and options pipeline (dateStyle: 'short').

Testing

  • cargo test -p boa_engine --lib -- date::tests::date_proto_to_locale_string_intl (without intl; test is skipped)
  • cargo test -p boa_engine --features intl_bundled --lib -- date::tests::date_proto_to_locale_string_intl (with intl)

@alienx5499 alienx5499 requested review from a team, jedel1043 and nekevss as code owners March 15, 2026 00:29
@github-actions github-actions bot added C-Tests Issues and PRs related to the tests. C-Builtins PRs and Issues related to builtins/intrinsics C-Intl Changes related to the `Intl` implementation Waiting On Review Waiting on reviews from the maintainers labels Mar 15, 2026
@github-actions github-actions bot added this to the v1.0.0 milestone Mar 15, 2026
@github-actions
Copy link

github-actions bot commented Mar 15, 2026

Test262 conformance changes

Test result main count PR count difference
Total 52,963 52,963 0
Passed 50,073 50,079 +6
Ignored 2,072 2,072 0
Failed 818 812 -6
Panics 0 0 0
Conformance 94.54% 94.55% +0.01%
Fixed tests (6):
test/intl402/Date/prototype/this-value-invalid-date.js (previously Failed)
test/intl402/Date/prototype/this-value-non-date.js (previously Failed)
test/intl402/Date/prototype/taint-Intl-DateTimeFormat.js (previously Failed)
test/intl402/Date/prototype/throws-same-exceptions-as-DateTimeFormat.js (previously Failed)
test/intl402/Date/prototype/toLocaleString/default-options-object-prototype.js (previously Failed)
test/staging/sm/misc/builtin-methods-reject-null-undefined-this.js (previously Failed)

Tested main commit: 197b736bb87523a14b41834c078adbec3059d237
Tested PR commit: 60b64009c79053522578466b33de32416a2f0e33
Compare commits: 197b736...60b6400

@jedel1043 jedel1043 added Waiting On Author Waiting on PR changes from the author and removed Waiting On Review Waiting on reviews from the maintainers labels Mar 15, 2026
@github-actions github-actions bot added the Waiting On Review Waiting on reviews from the maintainers label Mar 15, 2026
@codecov
Copy link

codecov bot commented Mar 15, 2026

Codecov Report

❌ Patch coverage is 95.00000% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 59.32%. Comparing base (6ddc2b4) to head (60b6400).
⚠️ Report is 891 commits behind head on main.

Files with missing lines Patch % Lines
...e/engine/src/builtins/intl/date_time_format/mod.rs 94.82% 3 Missing ⚠️
core/engine/src/builtins/date/mod.rs 95.23% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #5080       +/-   ##
===========================================
+ Coverage   47.24%   59.32%   +12.08%     
===========================================
  Files         476      563       +87     
  Lines       46892    62848    +15956     
===========================================
+ Hits        22154    37285    +15131     
- Misses      24738    25563      +825     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Member

@nekevss nekevss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed a couple things while reviewing this.

func.call(this, &[], context)
}

/// Returns the `[[DateValue]]` internal slot (RequireInternalSlot(dateObject, `[[DateValue]]`)).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: accessing the inner field should remain as the current style.

// Let dateObject be the this value.
// Perform ? RequireInternalSlot(dateObject, [[DateValue]]).
// Let x be dateObject.[[DateValue]].
let t = Self::this_date_value(this)?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: these steps are only applicable to the intl flagged implementation.

Err(JsError::from_opaque(JsValue::new(js_string!(
"Function Unimplemented]"
))))
// Let dateObject be the this value.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: style, include the step numbers alongside the spec steps

let needs_defaults = format_options.check_dtf_type(date_time_format_type);
// d. If needDefaults is true and defaults is either date or all, then
if needs_defaults && defaults != FormatDefaults::Time {
if needs_defaults && (defaults == FormatDefaults::All || defaults == FormatDefaults::Date) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: why was this changed? The previous looks correct and acts in less steps

context: &mut Context,
) -> JsResult<JsString> {
// FormatDateTime / PartitionDateTimePattern: TimeClip, then ToLocalTime, then format.
let x = time_clip(timestamp);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: we should not be handling this logic again.

We already handle this logic in two different places. There should not be a reason to implement it a second time. Maybe you're looking for ToLocalTime?

@alienx5499 alienx5499 force-pushed the feat/5075-date-tolocalestring branch from fa1bd92 to 755481e Compare March 15, 2026 21:49
@alienx5499 alienx5499 requested a review from nekevss March 15, 2026 21:52
@alienx5499
Copy link
Contributor Author

Hi @nekevss,

I've pushed updates addressing the review comments and resolved the outdated threads. Could you please take another look when you have time?

Thanks!

@jedel1043
Copy link
Member

Deferring to @nekevss for the final review, but LGTM from my side

@jedel1043 jedel1043 removed their request for review March 16, 2026 20:32
@jedel1043 jedel1043 removed the Waiting On Author Waiting on PR changes from the author label Mar 16, 2026
Copy link
Member

@nekevss nekevss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think one last issue and then this should probably be good.

timestamp: f64,
context: &mut Context,
) -> JsResult<JsString> {
let time_zone_offset = match dtf.time_zone {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: keep the doc lines that are applied with the methods.

Adapting dtf can be incredibly complicated, and this function is probably going to need to be updated / reworked in order to support temporal. So keeping the comments in this instance is very important.

@alienx5499 alienx5499 changed the title feat(intl): implement Date.prototype.toLocaleString, toLocaleDateStri… feat(intl): implement Date.prototype.toLocaleString, toLocaleDateString, and toLocaleTimeString Mar 17, 2026
@alienx5499
Copy link
Contributor Author

Hi @nekevss, I’ve pushed commit 6b270bf addressing your comment.

It keeps the spec step documentation alongside format_timestamp_with_dtf and introduces a time_zone binding to better mirror the spec flow and reuse the value.

Would appreciate a re-review when you have time.

@alienx5499 alienx5499 requested a review from nekevss March 17, 2026 10:58
@alienx5499
Copy link
Contributor Author

Hi @nekevss,

Just following up on this, I’ve addressed all the previous review comments and incorporated the requested changes.

Please let me know if there’s anything else I should update or refine. Happy to iterate further.

Thanks!

@jedel1043
Copy link
Member

Please don't repeatedly ping maintainers. A single request for review is enough. We'll review when we have the time

Copy link
Member

@nekevss nekevss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally looks good to me.

We'll have to keep in mind how this may need to expand in order to support Temporal in the future, but that's all TBD

@nekevss nekevss added this pull request to the merge queue Mar 19, 2026
Merged via the queue into boa-dev:main with commit 26271b7 Mar 19, 2026
22 checks passed
@github-actions github-actions bot removed the Waiting On Review Waiting on reviews from the maintainers label Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-Builtins PRs and Issues related to builtins/intrinsics C-Intl Changes related to the `Intl` implementation C-Tests Issues and PRs related to the tests.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Date.prototype.toLocaleString and friends

3 participants