Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

@formatjs/ecma402-abstract

Package Overview
Dependencies
Maintainers
3
Versions
92
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@formatjs/ecma402-abstract - npm Package Compare versions

Comparing version
3.0.3
to
3.0.4
+12
NumberFormat/decimal-cache.d.ts
import { Decimal } from 'decimal.js';
/**
* Cached function to compute powers of 10 for Decimal.js operations.
* This cache significantly reduces overhead in ComputeExponent and ToRawFixed
* by memoizing expensive Decimal.pow(10, n) calculations.
*
* Common exponents (e.g., -20 to 20) are used repeatedly in number formatting,
* so caching provides substantial performance benefits.
*
* @param exponent - Can be a number or Decimal. If Decimal, it will be converted to string for cache key.
*/
export declare const getPowerOf10: (exponent: number | Decimal) => Decimal;
import { Decimal } from 'decimal.js';
import { memoize } from '@formatjs/fast-memoize';
/**
* Cached function to compute powers of 10 for Decimal.js operations.
* This cache significantly reduces overhead in ComputeExponent and ToRawFixed
* by memoizing expensive Decimal.pow(10, n) calculations.
*
* Common exponents (e.g., -20 to 20) are used repeatedly in number formatting,
* so caching provides substantial performance benefits.
*
* @param exponent - Can be a number or Decimal. If Decimal, it will be converted to string for cache key.
*/
export var getPowerOf10 = memoize(function (exponent) {
return Decimal.pow(10, exponent);
});
+30
-3
import { Decimal } from 'decimal.js';
import { ComputeExponentForMagnitude } from './ComputeExponentForMagnitude.js';
import { FormatNumericToString } from './FormatNumericToString.js';
import { getPowerOf10 } from './decimal-cache.js';
/**

@@ -18,6 +19,20 @@ * The abstract operation ComputeExponent computes an exponent (power of ten) by which to scale x

}
var magnitude = x.log(10).floor();
// Fast path for simple numbers
// If x can be represented as a safe integer, use native Math.log10
var xNum = x.toNumber();
var magnitude;
if (Number.isFinite(xNum) &&
Number.isSafeInteger(xNum) &&
xNum > 0 &&
xNum <= 999999) {
// Use fast native logarithm for simple positive integers
var magNum = Math.floor(Math.log10(xNum));
magnitude = new Decimal(magNum);
}
else {
magnitude = x.log(10).floor();
}
var exponent = ComputeExponentForMagnitude(internalSlots, magnitude);
// Preserve more precision by doing multiplication when exponent is negative.
x = x.times(Decimal.pow(10, -exponent));
x = x.times(getPowerOf10(-exponent));
var formatNumberResult = FormatNumericToString(internalSlots, x);

@@ -27,3 +42,15 @@ if (formatNumberResult.roundedNumber.isZero()) {

}
var newMagnitude = formatNumberResult.roundedNumber.log(10).floor();
// Fast path for simple rounded numbers
var roundedNum = formatNumberResult.roundedNumber.toNumber();
var newMagnitude;
if (Number.isFinite(roundedNum) &&
Number.isSafeInteger(roundedNum) &&
roundedNum > 0 &&
roundedNum <= 999999) {
var newMagNum = Math.floor(Math.log10(roundedNum));
newMagnitude = new Decimal(newMagNum);
}
else {
newMagnitude = formatNumberResult.roundedNumber.log(10).floor();
}
if (newMagnitude.eq(magnitude.minus(exponent))) {

@@ -30,0 +57,0 @@ return [exponent, magnitude.toNumber()];

+2
-1
import { Decimal } from 'decimal.js';
import { invariant } from '../utils.js';
import { getPowerOf10 } from './decimal-cache.js';
Decimal.set({

@@ -40,3 +41,3 @@ toExpPos: 100,

}
var num = Decimal.pow(10, magnitude).toString();
var num = getPowerOf10(magnitude).toString();
var thresholds = Object.keys(thresholdMap); // TODO: this can be pre-processed

@@ -43,0 +44,0 @@ if (num < thresholds[0]) {

import { Decimal } from 'decimal.js';
import { S_UNICODE_REGEX } from '../regex.generated.js';
import { getPowerOf10 } from './decimal-cache.js';
import { digitMapping } from './digit-mapping.generated.js';

@@ -166,5 +167,3 @@ import { GetUnsignedRoundingMode } from './GetUnsignedRoundingMode.js';

if (currencyNameData) {
unitName = selectPlural(pl, numberResult.roundedNumber
.times(Decimal.pow(10, exponent))
.toNumber(), currencyNameData.displayName);
unitName = selectPlural(pl, numberResult.roundedNumber.times(getPowerOf10(exponent)).toNumber(), currencyNameData.displayName);
}

@@ -206,5 +205,3 @@ else {

// Simple unit pattern
unitPattern = selectPlural(pl, numberResult.roundedNumber
.times(Decimal.pow(10, exponent))
.toNumber(), data.units.simple[unit][unitDisplay]);
unitPattern = selectPlural(pl, numberResult.roundedNumber.times(getPowerOf10(exponent)).toNumber(), data.units.simple[unit][unitDisplay]);
}

@@ -217,5 +214,3 @@ else {

unitData = data.units.simple[numeratorUnit];
var numeratorUnitPattern = selectPlural(pl, numberResult.roundedNumber
.times(Decimal.pow(10, exponent))
.toNumber(), data.units.simple[numeratorUnit][unitDisplay]);
var numeratorUnitPattern = selectPlural(pl, numberResult.roundedNumber.times(getPowerOf10(exponent)).toNumber(), data.units.simple[numeratorUnit][unitDisplay]);
var perUnitPattern = data.units.simple[denominatorUnit].perUnit[unitDisplay];

@@ -222,0 +217,0 @@ if (perUnitPattern) {

@@ -1,2 +0,1 @@

import { Decimal } from 'decimal.js';
import { invariant } from '../utils.js';

@@ -6,2 +5,3 @@ import { ComputeExponent } from './ComputeExponent.js';

import { FormatNumericToString } from './FormatNumericToString.js';
import { getPowerOf10 } from './decimal-cache.js';
/**

@@ -49,3 +49,3 @@ * https://tc39.es/ecma402/#sec-partitionnumberpattern

// 8.d. Let x be x × 10^(-exponent).
x = x.times(Decimal.pow(10, -exponent));
x = x.times(getPowerOf10(-exponent));
}

@@ -52,0 +52,0 @@ // 8.e. Let formatNumberResult be FormatNumericToString(internalSlots, x).

import { Decimal } from 'decimal.js';
import { repeat } from '../utils.js';
import { ApplyUnsignedRoundingMode } from './ApplyUnsignedRoundingMode.js';
import { getPowerOf10 } from './decimal-cache.js';
//IMPL: Setting Decimal configuration

@@ -10,7 +11,7 @@ Decimal.set({

function ToRawFixedFn(n, f) {
return n.times(Decimal.pow(10, -f));
return n.times(getPowerOf10(-f));
}
//IMPL: Helper function to find n1 and r1
function findN1R1(x, f, roundingIncrement) {
var nx = x.times(Decimal.pow(10, f)).floor();
var nx = x.times(getPowerOf10(f)).floor();
var n1 = nx.div(roundingIncrement).floor().times(roundingIncrement);

@@ -25,3 +26,3 @@ var r1 = ToRawFixedFn(n1, f);

function findN2R2(x, f, roundingIncrement) {
var nx = x.times(Decimal.pow(10, f)).ceil();
var nx = x.times(getPowerOf10(f)).ceil();
var n2 = nx.div(roundingIncrement).ceil().times(roundingIncrement);

@@ -28,0 +29,0 @@ var r2 = ToRawFixedFn(n2, f);

@@ -1,15 +0,50 @@

import { Decimal } from 'decimal.js';
import { ZERO } from '../constants.js';
import { invariant, repeat } from '../utils.js';
import { ApplyUnsignedRoundingMode } from './ApplyUnsignedRoundingMode.js';
//IMPL: Helper function to find n1, e1, and r1
import { getPowerOf10 } from './decimal-cache.js';
//IMPL: Helper function to find n1, e1, and r1 using direct calculation
function findN1E1R1(x, p) {
var maxN1 = Decimal.pow(10, p);
var minN1 = Decimal.pow(10, p - 1);
var maxN1 = getPowerOf10(p);
var minN1 = getPowerOf10(p - 1);
// Direct calculation: compute e1 from logarithm
// e1 is the exponent such that n1 * 10^(e1-p+1) <= x
// Taking log: log(n1) + (e1-p+1)*log(10) <= log(x)
// Since n1 is between 10^(p-1) and 10^p, we have:
// (p-1) + (e1-p+1) <= log10(x) < p + (e1-p+1)
// Simplifying: e1 <= log10(x) < e1 + 1
// Therefore: e1 = floor(log10(x))
var log10x = x.log(10);
var e1 = log10x.floor();
// Calculate n1 and r1 from e1
var divisor = getPowerOf10(e1.minus(p).plus(1));
var n1 = x.div(divisor).floor();
var r1 = n1.times(divisor);
// Verify and adjust if n1 is out of bounds
// This handles edge cases near powers of 10
if (n1.greaterThanOrEqualTo(maxN1)) {
e1 = e1.plus(1);
var newDivisor = getPowerOf10(e1.minus(p).plus(1));
n1 = x.div(newDivisor).floor();
r1 = n1.times(newDivisor);
}
else if (n1.lessThan(minN1)) {
e1 = e1.minus(1);
var newDivisor = getPowerOf10(e1.minus(p).plus(1));
n1 = x.div(newDivisor).floor();
r1 = n1.times(newDivisor);
}
// Final verification with fallback to iterative search if needed
if (r1.lessThanOrEqualTo(x) &&
n1.lessThan(maxN1) &&
n1.greaterThanOrEqualTo(minN1)) {
return { n1: n1, e1: e1, r1: r1 };
}
// Fallback: iterative search (should rarely be needed)
var maxE1 = x.div(minN1).log(10).plus(p).minus(1).ceil();
var currentE1 = maxE1;
while (true) {
var currentN1 = x.div(Decimal.pow(10, currentE1.minus(p).plus(1))).floor();
var currentDivisor = getPowerOf10(currentE1.minus(p).plus(1));
var currentN1 = x.div(currentDivisor).floor();
if (currentN1.lessThan(maxN1) && currentN1.greaterThanOrEqualTo(minN1)) {
var currentR1 = currentN1.times(Decimal.pow(10, currentE1.minus(p).plus(1)));
var currentR1 = currentN1.times(currentDivisor);
if (currentR1.lessThanOrEqualTo(x)) {

@@ -26,12 +61,40 @@ return {

}
//IMPL: Helper function to find n2, e2, and r2
//IMPL: Helper function to find n2, e2, and r2 using direct calculation
function findN2E2R2(x, p) {
var maxN2 = Decimal.pow(10, p);
var minN2 = Decimal.pow(10, p - 1);
var maxN2 = getPowerOf10(p);
var minN2 = getPowerOf10(p - 1);
// Direct calculation: similar to findN1E1R1 but with ceiling
var log10x = x.log(10);
var e2 = log10x.floor();
// Calculate n2 and r2 from e2
var divisor = getPowerOf10(e2.minus(p).plus(1));
var n2 = x.div(divisor).ceil();
var r2 = n2.times(divisor);
// Verify and adjust if n2 is out of bounds
if (n2.greaterThanOrEqualTo(maxN2)) {
e2 = e2.plus(1);
var newDivisor = getPowerOf10(e2.minus(p).plus(1));
n2 = x.div(newDivisor).ceil();
r2 = n2.times(newDivisor);
}
else if (n2.lessThan(minN2)) {
e2 = e2.minus(1);
var newDivisor = getPowerOf10(e2.minus(p).plus(1));
n2 = x.div(newDivisor).ceil();
r2 = n2.times(newDivisor);
}
// Final verification with fallback to iterative search if needed
if (r2.greaterThanOrEqualTo(x) &&
n2.lessThan(maxN2) &&
n2.greaterThanOrEqualTo(minN2)) {
return { n2: n2, e2: e2, r2: r2 };
}
// Fallback: iterative search (should rarely be needed)
var minE2 = x.div(maxN2).log(10).plus(p).minus(1).floor();
var currentE2 = minE2;
while (true) {
var currentN2 = x.div(Decimal.pow(10, currentE2.minus(p).plus(1))).ceil();
var currentDivisor = getPowerOf10(currentE2.minus(p).plus(1));
var currentN2 = x.div(currentDivisor).ceil();
if (currentN2.lessThan(maxN2) && currentN2.greaterThanOrEqualTo(minN2)) {
var currentR2 = currentN2.times(Decimal.pow(10, currentE2.minus(p).plus(1)));
var currentR2 = currentN2.times(currentDivisor);
if (currentR2.greaterThanOrEqualTo(x)) {

@@ -38,0 +101,0 @@ return {

{
"name": "@formatjs/ecma402-abstract",
"description": "A collection of implementation for ECMAScript abstract operations",
"version": "3.0.3",
"version": "3.0.4",
"license": "MIT",

@@ -6,0 +6,0 @@ "author": "Long Ho <holevietlong@gmail.com",