Skip to content
This repository has been archived by the owner on Apr 14, 2021. It is now read-only.

Bug when adding NumberFormat Polyfill #315

Open
DavidLangva opened this issue Jul 23, 2018 · 1 comment
Open

Bug when adding NumberFormat Polyfill #315

DavidLangva opened this issue Jul 23, 2018 · 1 comment

Comments

@DavidLangva
Copy link

Replication of Issue: https://repl.it/repls/GrouchyBruisedMigration
Bug: https://github.com/andyearnshaw/Intl.js/blob/v1.2.4/src/11.numberformat.js#L47-L56

Following the recommendations on the README, we are reassigning NumberFormat in case areIntlLocalesSupported returns false:

if (global.Intl) {
    if (!areIntlLocalesSupported(localesMyAppSupports)) {
        var IntlPolyfill    = require('intl');
        Intl.NumberFormat   = IntlPolyfill.NumberFormat;
        Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat;
    }
}

However, because we reassign the Global Intl.NumberFormat to the polyfilled polyfillIntl.NumberFormat, we have the following problem when calling Intl.NumberFormat: !this || this === Intl always evaluate to false:

if (!this || this === Intl){
  return new Intl.NumberFormat(locales, options); 
}
return InitializeNumberFormat(toObject(this), locales, options);}

Because NumberFormat is a function called on the global Intl Object the this keyword refers to the global Intl object. Thus the if statement will never be satisfied (this will always be defined and the global Intl object will never === the local/polyfilled Intl object ) thus InitializeNumberFormat will be called every time.

Also, the first time InitializeNumberFormat is called, it is passed the global Intl object (via the this keyword) and not a NumberFormat Object
InitializeNumberFormat(toObject(this), locales, options)

Then

Intl.NumberFormat('en-US');
Intl.NumberFormat('fr-FR');

This raises a type error TypeError: 'this' object has already been initialized as an Intl object

The workaround is to use it as a function rather than a method so that the this keyword is not bound to the global Intl Object:

const intlNumberFormat = Intl.NumberFormat; 
intlNumberFormat('en-US');
intlNumberFormat('fr-FR');

OR to completely replace Intl in the initialization step:

if (global.Intl) {
    if (!areIntlLocalesSupported(localesMyAppSupports)) {
        var IntlPolyfill    = require('intl');
        Intl = IntlPolyfill;
    }
}
@serhiipalash
Copy link

We have the same problem with using moment-duration-format library in our React Native app on Android. In Android JS Engine global.Intl is available, but NumberFormat is missing in it, and moment-duration-format library checks if Intl.NumberFormat is avaialbe on load, so our app just crashes on start. The only solution is to downgrade to previous versions of moment-duration-format, in which there is no call of Intl.NumberFormat on load module.

@DavidLangva where this code lies in this repository? I didn't find it.

if (!this || this === Intl){
  return new Intl.NumberFormat(locales, options); 
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants