Skip to content

Commit d83ed9a

Browse files
authored
fix: clone settings locale data (#96)
* fix: clone settings locale data * fix: address locale data review feedback * docs: clarify locale data clone comment
1 parent 8c3af50 commit d83ed9a

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

src/settings/settings.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,15 @@ describe('settings', () => {
2323
settings.setLocale(LOCALE);
2424
expect(settings.getLocale()).toEqual(LOCALE);
2525
});
26+
27+
it('should clone locale data with function values', () => {
28+
settings.setLocale('en');
29+
30+
const localeData = settings.getLocaleData();
31+
const nextLocaleData = settings.getLocaleData();
32+
33+
expect(typeof localeData.ordinal).toBe('function');
34+
expect(localeData).not.toBe(nextLocaleData);
35+
expect(localeData.formats).not.toBe(nextLocaleData.formats);
36+
});
2637
});

src/settings/settings.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,23 @@ import {normalizeTimeZone} from '../timeZone';
55
import {localeLoaders} from './locales';
66
import type {Locale, Parser, PublicSettings, UpdateLocaleConfig} from './types';
77

8+
function cloneLocaleData<T>(value: T): T {
9+
if (!value || typeof value !== 'object') {
10+
return value;
11+
}
12+
13+
if (Array.isArray(value)) {
14+
return value.map((item) => cloneLocaleData(item)) as T;
15+
}
16+
17+
// Dayjs locale data contains function fields such as ordinal.
18+
// Clone array/plain-object containers so callers can safely mutate the result,
19+
// while keeping locale functions callable by reference.
20+
return Object.fromEntries(
21+
Object.entries(value).map(([key, item]) => [key, cloneLocaleData(item)]),
22+
) as T;
23+
}
24+
825
class Settings implements PublicSettings {
926
// 'en' - preloaded locale in dayjs
1027
private loadedLocales = new Set(['en']);
@@ -50,7 +67,7 @@ class Settings implements PublicSettings {
5067
throw new Error('There is something really wrong happening. Locale data is absent.');
5168
}
5269

53-
return structuredClone(localeObject) as Locale;
70+
return cloneLocaleData(localeObject) as Locale;
5471
}
5572

5673
setLocale(locale: string) {

0 commit comments

Comments
 (0)