Skip to content

Support BigInt in Intl.NumberFormat.format() and formatToParts()#1930

Draft
tmikov wants to merge 1 commit intofacebook:static_hfrom
tmikov:issue-1928
Draft

Support BigInt in Intl.NumberFormat.format() and formatToParts()#1930
tmikov wants to merge 1 commit intofacebook:static_hfrom
tmikov:issue-1928

Conversation

@tmikov
Copy link
Contributor

@tmikov tmikov commented Mar 5, 2026

Per ECMA-402 §15.5.4, BigInt is a valid argument to NumberFormat format and formatToParts methods. Previously these called toNumber_RJS() which throws TypeError on BigInt inputs.

Replace toNumber_RJS() with toNumeric_RJS() and, when the result is a BigInt, convert it to a decimal string via bigint::toString() and pass it through new string-based format/formatToParts overloads on each platform backend (ICU stub, Apple via NSDecimalNumber, Android via java.math.BigDecimal). This preserves exact precision for arbitrarily large BigInts.

Fixes #1928

Per ECMA-402 §15.5.4, BigInt is a valid argument to NumberFormat format
and formatToParts methods. Previously these called toNumber_RJS() which
throws TypeError on BigInt inputs.

Replace toNumber_RJS() with toNumeric_RJS() and, when the result is a
BigInt, convert it to a decimal string via bigint::toString() and pass
it through new string-based format/formatToParts overloads on each
platform backend (ICU stub, Apple via NSDecimalNumber, Android via
java.math.BigDecimal). This preserves exact precision for arbitrarily
large BigInts.

Fixes facebook#1928
@meta-cla meta-cla bot added the CLA Signed Do not delete this pull request or issue due to inactivity. label Mar 5, 2026
@tmikov tmikov requested a review from Copilot March 5, 2026 01:46
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds ECMA-402–compliant BigInt handling to Intl.NumberFormat.prototype.format() and formatToParts() by routing BigInt inputs through string-based formatting paths in the platform Intl backends.

Changes:

  • Switch Intl.NumberFormat argument coercion from toNumber_RJS() to toNumeric_RJS() and add BigInt-specific formatting branches.
  • Introduce string overloads for format / formatToParts across the platform Intl layer (C++/JNI + Java backends).
  • Expand the regression test to validate formatted output for several BigInt values.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/hermes/regress-intl-number-format-bigint-input.js Updates regression test to assert concrete formatted outputs for BigInt format() calls.
lib/VM/JSLib/Intl.cpp Accepts BigInt via toNumeric_RJS() and formats BigInt by converting to a base-10 string.
lib/Platform/Intl/java/com/facebook/hermes/intl/PlatformNumberFormatterICU.java Adds format(String) / formatToParts(String) using BigDecimal for ICU-backed Android formatting.
lib/Platform/Intl/java/com/facebook/hermes/intl/PlatformNumberFormatterAndroid.java Adds format(String) / formatToParts(String) using BigDecimal for the legacy Android formatter.
lib/Platform/Intl/java/com/facebook/hermes/intl/NumberFormat.java Adds JNI-exposed format(String) / formatToParts(String) overloads that delegate to the platform formatter.
lib/Platform/Intl/java/com/facebook/hermes/intl/IPlatformNumberFormatter.java Extends the platform formatter interface with string overloads for BigInt formatting.
lib/Platform/Intl/PlatformIntlICU.cpp Adds string overload stubs for ICU (non-Android/Apple) NumberFormat formatting/parts.
lib/Platform/Intl/PlatformIntlApple.mm Adds string overload for Apple NumberFormat using NSDecimalNumber (and wires through base class).
lib/Platform/Intl/PlatformIntlAndroid.cpp Adds JNI bindings to call the new Java format(String) / formatToParts(String) overloads.
include/hermes/Platform/Intl/PlatformIntl.h Extends C++ platform Intl NumberFormat API with string overloads.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +11 to 13
// Ensures Hermes Intl's NumberFormat correctly formats BigInt inputs.
var nf = new Intl.NumberFormat("en", undefined);

Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

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

This regression test now validates BigInt handling for format(), but the PR also changes formatToParts() to accept BigInt. Adding at least one formatToParts(…n) assertion (including a negative BigInt case) would help prevent regressions in the new BigInt-specific formatToParts path.

Copilot uses AI. Check for mistakes.
Comment on lines +717 to +721
if (keyIterator.hasNext()) {
key = mPlatformNumberFormatter.fieldToString(keyIterator.next(), 0);
} else {
key = "literal";
}
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

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

In the BigInt string overload of formatToParts(), fieldToString() is always called with 0, which makes the SIGN field mapping incorrect for negative BigInt values (it will be reported as plusSign instead of minusSign in the ICU backend). Consider deriving the sign from n (e.g., leading '-') and passing a negative value when needed, or adding a dedicated fieldToString overload for non-double inputs so sign classification stays correct without lossy numeric conversion.

Copilot uses AI. Check for mistakes.
Comment on lines +358 to +359
BigDecimal bigDecimal = new BigDecimal(n);
try {
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

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

BigDecimal bigDecimal = new BigDecimal(n); is executed before the try/catch, so an invalid decimal string would throw NumberFormatException that bypasses your fallback handling. Move the BigDecimal construction into the try block (or add an outer catch) so the method’s error handling is actually effective.

Suggested change
BigDecimal bigDecimal = new BigDecimal(n);
try {
BigDecimal bigDecimal = null;
try {
bigDecimal = new BigDecimal(n);

Copilot uses AI. Check for mistakes.
@meta-codesync
Copy link

meta-codesync bot commented Mar 5, 2026

@tmikov has imported this pull request. If you are a Meta employee, you can view this in D95306891.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed Do not delete this pull request or issue due to inactivity.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Intl.NumberFormat.format() throws "Cannot convert BigInt to number" when passed a bigint on Android

2 participants