* Transforms a number to a locale string based on a style and a format.
( value: number, pattern: ParsedNumberFormat, locale: string, groupSymbol: NumberSymbol, decimalSymbol: NumberSymbol, digitsInfo?: string, isPercent = false, )
| 31 | * Transforms a number to a locale string based on a style and a format. |
| 32 | */ |
| 33 | function formatNumberToLocaleString( |
| 34 | value: number, |
| 35 | pattern: ParsedNumberFormat, |
| 36 | locale: string, |
| 37 | groupSymbol: NumberSymbol, |
| 38 | decimalSymbol: NumberSymbol, |
| 39 | digitsInfo?: string, |
| 40 | isPercent = false, |
| 41 | ): string { |
| 42 | let formattedText = ''; |
| 43 | let isZero = false; |
| 44 | |
| 45 | if (!isFinite(value)) { |
| 46 | formattedText = getLocaleNumberSymbol(locale, NumberSymbol.Infinity); |
| 47 | } else { |
| 48 | let parsedNumber = parseNumber(value); |
| 49 | |
| 50 | if (isPercent) { |
| 51 | parsedNumber = toPercent(parsedNumber); |
| 52 | } |
| 53 | |
| 54 | let minInt = pattern.minInt; |
| 55 | let minFraction = pattern.minFrac; |
| 56 | let maxFraction = pattern.maxFrac; |
| 57 | |
| 58 | if (digitsInfo) { |
| 59 | const parts = digitsInfo.match(NUMBER_FORMAT_REGEXP); |
| 60 | if (parts === null) { |
| 61 | throw new RuntimeError( |
| 62 | RuntimeErrorCode.INVALID_DIGIT_INFO, |
| 63 | ngDevMode && `${digitsInfo} is not a valid digit info`, |
| 64 | ); |
| 65 | } |
| 66 | const minIntPart = parts[1]; |
| 67 | const minFractionPart = parts[3]; |
| 68 | const maxFractionPart = parts[5]; |
| 69 | if (minIntPart != null) { |
| 70 | minInt = parseIntAutoRadix(minIntPart); |
| 71 | } |
| 72 | if (minFractionPart != null) { |
| 73 | minFraction = parseIntAutoRadix(minFractionPart); |
| 74 | } |
| 75 | if (maxFractionPart != null) { |
| 76 | maxFraction = parseIntAutoRadix(maxFractionPart); |
| 77 | } else if (minFractionPart != null && minFraction > maxFraction) { |
| 78 | maxFraction = minFraction; |
| 79 | } |
| 80 | |
| 81 | // Prevent DoS via resource exhaustion by capping the maximum padding iterations |
| 82 | const MAX_ALLOWED_DIGITS = 100; |
| 83 | if ( |
| 84 | minInt > MAX_ALLOWED_DIGITS || |
| 85 | minFraction > MAX_ALLOWED_DIGITS || |
| 86 | maxFraction > MAX_ALLOWED_DIGITS |
| 87 | ) { |
| 88 | throw new RuntimeError( |
| 89 | RuntimeErrorCode.INVALID_DIGIT_INFO, |
| 90 | ngDevMode && |
no test coverage detected
searching dependent graphs…