Skip to content

Commit f937ba7

Browse files
authored
[number field] Fix formatter locale cache (#4999)
1 parent 747447c commit f937ba7

6 files changed

Lines changed: 46 additions & 11 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { expect } from 'vitest';
2+
import { getFilter } from './filter';
3+
4+
describe('getFilter', () => {
5+
it('caches different Intl.Locale objects separately', () => {
6+
const filter1 = getFilter({ locale: new Intl.Locale('fr-FR') });
7+
const filter2 = getFilter({ locale: new Intl.Locale('en-US') });
8+
9+
expect(filter1).not.toBe(filter2);
10+
});
11+
});

packages/react/src/internals/filter.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { stringifyAsLabel } from './resolveValueLabel';
2+
import { stringifyLocale } from '../utils/stringifyLocale';
23

34
const filterCache = new Map<string, Filter>();
45

@@ -63,16 +64,6 @@ export function getFilter(options: GetFilterParameters = {}): Filter {
6364
return filter;
6465
}
6566

66-
function stringifyLocale(locale?: Intl.LocalesArgument): string {
67-
if (Array.isArray(locale)) {
68-
return locale.map((value) => stringifyLocale(value)).join(',');
69-
}
70-
if (locale == null) {
71-
return '';
72-
}
73-
return String(locale);
74-
}
75-
7667
export interface GetFilterParameters extends Intl.CollatorOptions {
7768
/**
7869
* The locale to use for string comparison.

packages/react/src/utils/formatNumber.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ describe('NumberField format', () => {
1515
const formatter2 = getFormatter(undefined, getOptions());
1616
expect(formatter1).toBe(formatter2);
1717
});
18+
19+
it('caches different Intl.Locale objects separately', () => {
20+
const formatter1 = getFormatter(new Intl.Locale('fr-FR'), getOptions());
21+
const formatter2 = getFormatter(new Intl.Locale('en-US'), getOptions());
22+
23+
expect(formatter1).not.toBe(formatter2);
24+
expect(formatter1.resolvedOptions().locale).toBe('fr-FR');
25+
expect(formatter2.resolvedOptions().locale).toBe('en-US');
26+
});
1827
});
1928

2029
describe('formatNumber', () => {

packages/react/src/utils/formatNumber.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import { stringifyLocale } from './stringifyLocale';
2+
13
export const cache = new Map<string, Intl.NumberFormat>();
24

35
export function getFormatter(locale?: Intl.LocalesArgument, options?: Intl.NumberFormatOptions) {
4-
const optionsString = JSON.stringify({ locale, options });
6+
const optionsString = JSON.stringify({ locale: stringifyLocale(locale), options });
57
const cachedFormatter = cache.get(optionsString);
68

79
if (cachedFormatter) {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { expect } from 'vitest';
2+
import { stringifyLocale } from './stringifyLocale';
3+
4+
describe('stringifyLocale', () => {
5+
it('stringifies Intl locale arguments for cache keys', () => {
6+
expect(stringifyLocale()).toBe('');
7+
expect(stringifyLocale('en-US')).toBe('en-US');
8+
expect(stringifyLocale(new Intl.Locale('fr-FR'))).toBe('fr-FR');
9+
expect(stringifyLocale(['fr-FR', new Intl.Locale('en-US')])).toBe('fr-FR,en-US');
10+
});
11+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export function stringifyLocale(locale?: Intl.LocalesArgument): string {
2+
if (Array.isArray(locale)) {
3+
return locale.map((value) => stringifyLocale(value)).join(',');
4+
}
5+
6+
if (locale == null) {
7+
return '';
8+
}
9+
10+
return String(locale);
11+
}

0 commit comments

Comments
 (0)