hermes: Intl.NumberFormat notation: compact is not working on 0.71.7

Bug Description

  • I have run gradle clean and confirmed this bug does not occur with JSC

Hermes version: { “Bytecode Version”: 90, “Builtins Frozen”: false, “VM Experiments”: 0, “Build”: “Release”, “GC”: “hades (concurrent)”, “OSS Release Version”: “for RN 0.71.7”, “CommonJS Modules”: “None” }

React Native version (if any): 0.71.7" OS version (if any): 0.71.7" Platform (most likely one of arm64-v8a, armeabi-v7a, x86, x86_64): all

Steps To Reproduce

  1. Use Intl.NumberFormat with large number and notation as compact

code example:

function formatCompactNumber(number) {
  const formatter = Intl.NumberFormat("en", { notation: "compact" });
  console.log(formatter.format(number));
}

// the comments are what should be logged
formatCompactNumber(-57);               // -57
formatCompactNumber(999);               // 999
formatCompactNumber(8_554);             // 8.5K
formatCompactNumber(150_000);           // 150K
formatCompactNumber(3_237_512);         // 3.2M
formatCompactNumber(9_782_716_897);     // 9.8B
formatCompactNumber(7_899_693_036_970); // 7.9T


// below is what we got:
/*
 LOG  -57
 LOG  999
 LOG  8,554
 LOG  150,000
 LOG  3,237,512
 LOG  9,782,716,897
 LOG  7,899,693,036,970
*/

The Expected Behavior

Expected:

formatCompactNumber(150_000);           // 150K
formatCompactNumber(3_237_512);         // 3.2M
formatCompactNumber(9_782_716_897);     // 9.8B
formatCompactNumber(7_899_693_036_970); // 7.9T

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Reactions: 8
  • Comments: 20 (12 by maintainers)

Commits related to this issue

Most upvoted comments

Ok as a workaround you can use this function:

function customCompactFormat(number) {
    if (number < 1e3) {
        return number.toString();
    } else if (number < 1e6) {
        return Math.floor(number / 1e2) / 10 + 'K'; // Formats thousands
    } else if (number < 1e9) {
        return Math.floor(number / 1e5) / 10 + 'M'; // Formats millions
    } else {
        return Math.floor(number / 1e8) / 10 + 'B'; // Formats billions
    }
}

FYI, this is our plan for dealing with Intl problems: https://github.com/facebook/hermes/discussions/1211

@AndreiCalazans Thx. Even with import '@formatjs/intl-numberformat/polyfill-force' (and forcing all of the other @formatjs imports) it remains slower than without polyfill. It has significant impact on the JS Thread. Still hoping for native support 🤞

@jgo80 double check that formatjs ins’t using Hermes’ native Intl APIs since they are available formatjs won’t oveerride them. We had to patch shouldPolyfill calls within formatjs to always return true.

Hermes’ native Intl APIs are very slow.

@jobpaardekooper We could conditionally compile it out on older iOS versions, but this wouldn’t help in general until RN’s minimum iOS version is past 15+. (except for users who are willing to build Hermes from source)

is there a workaround for this? doesn’t work on android and ios for me

@AndreiCalazans I did not test it but in the docs at the Android 11 section it says notation: ‘compact’ has some rough edges on Android.

Regarding testing, we currently run against test262, which is the primary source of tests for both Android and iOS Intl implementations. You can take a look at our CI set-up here to see how it is done.

We also have some additional tests here that you can add to if you add features. Note that these are primarily for running on macOS.

Intl is enabled by default when you build with it, so you shouldn’t need to touch -Xintl unless you want to disable it.