From 9f571c4d013b9a40d86109a3ae838facd0445364 Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Wed, 29 Oct 2025 14:06:04 +0200 Subject: [PATCH 1/6] Add tests for keep-trailing-zeros proposal --- features.txt | 4 + .../value-decimal-string-trailing-zeros.js | 78 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js diff --git a/features.txt b/features.txt index a47a44b9b16..4521114bfc0 100644 --- a/features.txt +++ b/features.txt @@ -19,6 +19,10 @@ Intl.Locale-info # https://github.com/tc39/proposal-intl-numberformat-v3 Intl.NumberFormat-v3 +# Keep trailing zeros in Intl.NumberFormat and Intl.PluralRules +# https://github.com/tc39/proposal-intl-keep-trailing-zeros +keep-trailing-zeros + # Legacy RegExp features # https://github.com/tc39/proposal-regexp-legacy-features legacy-regexp diff --git a/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js b/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js new file mode 100644 index 00000000000..dad8e97771e --- /dev/null +++ b/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js @@ -0,0 +1,78 @@ +// Copyright (C) 2025 Mozilla Foundation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: pending +description: > + Intl.NumberFormat.prototype.format converts its argument (called value) to a + number using ToIntlMathematicalValue, and retains trailing zeros during formatting. +features: [Intl.NumberFormat-v3, keep-trailing-zeros] +locale: [en-US] +---*/ + +const nf = new Intl.NumberFormat('en-US', { maximumFractionDigits: 20 }); + +assert.sameValue(nf.format('0'), '0'); +assert.sameValue(nf.format('1'), '1'); +assert.sameValue(nf.format('0.0'), '0.0'); +assert.sameValue(nf.format('1.0'), '1.0'); +assert.sameValue(nf.format('10.0'), '10.0'); +assert.sameValue(nf.format('0.10'), '0.10'); +assert.sameValue(nf.format('0.010'), '0.010'); +assert.sameValue(nf.format('.10'), '0.10'); +assert.sameValue(nf.format('.0'), '0.0'); +assert.sameValue(nf.format('00.0'), '0.0'); +assert.sameValue(nf.format('001'), '1'); +assert.sameValue(nf.format('-0.00'), '-0.00'); +assert.sameValue(nf.format('-.00'), '-0.00'); +assert.sameValue(nf.format('3.100'), '3.100'); +assert.sameValue(nf.format('6.000000'), '6.000000'); +assert.sameValue(nf.format('1.230e1'), '12.30'); +assert.sameValue(nf.format('1.230e-2'), '0.0123'); + +// Default maximumfractionDigits is 3 +const nf2 = new Intl.NumberFormat('en-US', { minimumFractionDigits: 1 }); + +assert.sameValue(nf2.format('1'), '1.0'); +assert.sameValue(nf2.format('1.00'), '1.00'); +assert.sameValue(nf2.format('1.000000'), '1.000'); + +const nf3 = new Intl.NumberFormat('en-US', { + minimumSignificantDigits: 2, + maximumSignificantDigits: 4, +}); + +assert.sameValue(nf3.format('1'), '1.0'); +assert.sameValue(nf3.format('1.0'), '1.0'); +assert.sameValue(nf3.format('1.00'), '1.00'); +assert.sameValue(nf3.format('0.00'), '0.00'); +assert.sameValue(nf3.format('.00'), '0.00'); +assert.sameValue(nf3.format('1.000000'), '1.000'); + +const pf = new Intl.NumberFormat('en-US', { + style: 'percent', + maximumFractionDigits: 10, +}); + +assert.sameValue(pf.format('1.0'), '100%'); +assert.sameValue(pf.format('1.00'), '100%'); +assert.sameValue(pf.format('0.50'), '50%'); +assert.sameValue(pf.format('0.5000'), '50.00%'); + +const sf = new Intl.NumberFormat('en-US', { notation: 'scientific' }); + +assert.sameValue(sf.format('0.1'), '1E-1'); +assert.sameValue(sf.format('0.01'), '1E-2'); +assert.sameValue(sf.format('0.01200'), '1.200E-2'); +assert.sameValue(sf.format('120.0'), '1.200E2'); + +const spf = new Intl.NumberFormat('en-US', { + style: 'percent', + notation: 'scientific', + maximumFractionDigits: 10, +}); + +assert.sameValue(spf.format('0.0'), '0.0E0%'); +assert.sameValue(spf.format('1.0'), '1.0E2%'); +assert.sameValue(spf.format('1.00'), '1.00E2%'); +assert.sameValue(spf.format('0.50'), '5.0E1%'); +assert.sameValue(spf.format('0.5000'), '5.000E1%'); From f6804cc662647b1700850aecfae4bd161081283c Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Wed, 18 Feb 2026 11:10:51 +0200 Subject: [PATCH 2/6] Apply suggestions from code review Co-authored-by: Richard Gibson --- .../prototype/format/value-decimal-string-trailing-zeros.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js b/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js index dad8e97771e..1657c82d4d4 100644 --- a/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js +++ b/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js @@ -27,9 +27,9 @@ assert.sameValue(nf.format('-.00'), '-0.00'); assert.sameValue(nf.format('3.100'), '3.100'); assert.sameValue(nf.format('6.000000'), '6.000000'); assert.sameValue(nf.format('1.230e1'), '12.30'); -assert.sameValue(nf.format('1.230e-2'), '0.0123'); +assert.sameValue(nf.format('1.230e-2'), '0.01230'); -// Default maximumfractionDigits is 3 +// maximumFractionDigits defaults to 3 const nf2 = new Intl.NumberFormat('en-US', { minimumFractionDigits: 1 }); assert.sameValue(nf2.format('1'), '1.0'); From 86d997fb913dab155ba103ee024b24bd978b5db5 Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Thu, 19 Feb 2026 09:24:48 +0200 Subject: [PATCH 3/6] Add more tests for inputs with exponents & trailingZeroDisplay: "stripToMinimum" --- .../value-decimal-string-trailing-zeros.js | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js b/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js index 1657c82d4d4..cfbe10c478a 100644 --- a/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js +++ b/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js @@ -27,7 +27,13 @@ assert.sameValue(nf.format('-.00'), '-0.00'); assert.sameValue(nf.format('3.100'), '3.100'); assert.sameValue(nf.format('6.000000'), '6.000000'); assert.sameValue(nf.format('1.230e1'), '12.30'); +assert.sameValue(nf.format('1.230e0'), '1.230'); +assert.sameValue(nf.format('1.230e-1'), '0.1230'); assert.sameValue(nf.format('1.230e-2'), '0.01230'); +assert.sameValue(nf.format('12.30e-1'), '1.230'); +assert.sameValue(nf.format('12.30e-2'), '0.1230'); +assert.sameValue(nf.format('12.30e-3'), '0.01230'); +assert.sameValue(nf.format('1.2345e-1000'), '0.00000000000000000000'); // maximumFractionDigits defaults to 3 const nf2 = new Intl.NumberFormat('en-US', { minimumFractionDigits: 1 }); @@ -47,6 +53,21 @@ assert.sameValue(nf3.format('1.00'), '1.00'); assert.sameValue(nf3.format('0.00'), '0.00'); assert.sameValue(nf3.format('.00'), '0.00'); assert.sameValue(nf3.format('1.000000'), '1.000'); +assert.sameValue(nf3.format('1.99999'), '2.000'); + +const nf4 = new NumberFormat('en-US', { + minimumSignificantDigits: 2, + maximumSignificantDigits: 4, + trailingZeroDisplay: 'stripToMinimum', +}); + +assert.sameValue(nf4.format('1'), '1.0'); +assert.sameValue(nf4.format('1.0'), '1.0'); +assert.sameValue(nf4.format('1.00'), '1.0'); +assert.sameValue(nf4.format('0.00'), '0.0'); +assert.sameValue(nf4.format('.00'), '0.0'); +assert.sameValue(nf4.format('1.000000'), '1.0'); +assert.sameValue(nf4.format('1.99999'), '2.0'); const pf = new Intl.NumberFormat('en-US', { style: 'percent', @@ -64,6 +85,9 @@ assert.sameValue(sf.format('0.1'), '1E-1'); assert.sameValue(sf.format('0.01'), '1E-2'); assert.sameValue(sf.format('0.01200'), '1.200E-2'); assert.sameValue(sf.format('120.0'), '1.200E2'); +assert.sameValue(sf.format('12.00e-3'), '1.200E-2'); +assert.sameValue(sf.format('1.200e-3'), '1.200E-3'); +assert.sameValue(sf.format('.1200e-3'), '1.200E-4'); const spf = new Intl.NumberFormat('en-US', { style: 'percent', From 343c807c57e5b86c7ef1108c14f61e95ed8167b6 Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Thu, 26 Feb 2026 13:31:26 +0200 Subject: [PATCH 4/6] Fix trailing zero count when formatting '1.2345e-1000' --- .../prototype/format/value-decimal-string-trailing-zeros.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js b/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js index cfbe10c478a..1ed8cac7c64 100644 --- a/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js +++ b/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js @@ -33,7 +33,7 @@ assert.sameValue(nf.format('1.230e-2'), '0.01230'); assert.sameValue(nf.format('12.30e-1'), '1.230'); assert.sameValue(nf.format('12.30e-2'), '0.1230'); assert.sameValue(nf.format('12.30e-3'), '0.01230'); -assert.sameValue(nf.format('1.2345e-1000'), '0.00000000000000000000'); +assert.sameValue(nf.format('1.2345e-1000'), '0.0000'); // maximumFractionDigits defaults to 3 const nf2 = new Intl.NumberFormat('en-US', { minimumFractionDigits: 1 }); From e527698fb9bd1db0baa965c040db909de4d41e00 Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Mon, 2 Mar 2026 09:37:33 +0200 Subject: [PATCH 5/6] Add more tests --- .../prototype/format/value-decimal-string-trailing-zeros.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js b/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js index 1ed8cac7c64..3207517095a 100644 --- a/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js +++ b/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js @@ -41,6 +41,8 @@ const nf2 = new Intl.NumberFormat('en-US', { minimumFractionDigits: 1 }); assert.sameValue(nf2.format('1'), '1.0'); assert.sameValue(nf2.format('1.00'), '1.00'); assert.sameValue(nf2.format('1.000000'), '1.000'); +assert.sameValue(nf2.format('0.999'), '0.999'); +assert.sameValue(nf2.format('0.9999'), '1.000'); const nf3 = new Intl.NumberFormat('en-US', { minimumSignificantDigits: 2, @@ -54,6 +56,9 @@ assert.sameValue(nf3.format('0.00'), '0.00'); assert.sameValue(nf3.format('.00'), '0.00'); assert.sameValue(nf3.format('1.000000'), '1.000'); assert.sameValue(nf3.format('1.99999'), '2.000'); +assert.sameValue(nf3.format('1.2'), '1.2'); +assert.sameValue(nf3.format('0.12'), '0.12'); +assert.sameValue(nf3.format('0.012'), '0.012'); const nf4 = new NumberFormat('en-US', { minimumSignificantDigits: 2, From d7554010891cfd8decab57e793441a63cb66aaf1 Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Sat, 16 May 2026 17:17:58 +0300 Subject: [PATCH 6/6] Add tests for tc39/proposal-intl-keep-trailing-zeros#19 --- .../format/value-decimal-string-trailing-zeros.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js b/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js index 3207517095a..284e32522c4 100644 --- a/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js +++ b/test/intl402/NumberFormat/prototype/format/value-decimal-string-trailing-zeros.js @@ -33,7 +33,9 @@ assert.sameValue(nf.format('1.230e-2'), '0.01230'); assert.sameValue(nf.format('12.30e-1'), '1.230'); assert.sameValue(nf.format('12.30e-2'), '0.1230'); assert.sameValue(nf.format('12.30e-3'), '0.01230'); -assert.sameValue(nf.format('1.2345e-1000'), '0.0000'); +assert.sameValue(nf.format('1.2345e-21'), '0.00000000000000000000'); +assert.sameValue(nf.format('1.2345e-100'), '0.00000000000000000000'); +assert.sameValue(nf.format('1.2345e-1000'), '0.00000000000000000000'); // maximumFractionDigits defaults to 3 const nf2 = new Intl.NumberFormat('en-US', { minimumFractionDigits: 1 }); @@ -54,11 +56,14 @@ assert.sameValue(nf3.format('1.0'), '1.0'); assert.sameValue(nf3.format('1.00'), '1.00'); assert.sameValue(nf3.format('0.00'), '0.00'); assert.sameValue(nf3.format('.00'), '0.00'); +assert.sameValue(nf3.format('0.000000'), '0.000'); assert.sameValue(nf3.format('1.000000'), '1.000'); assert.sameValue(nf3.format('1.99999'), '2.000'); assert.sameValue(nf3.format('1.2'), '1.2'); assert.sameValue(nf3.format('0.12'), '0.12'); assert.sameValue(nf3.format('0.012'), '0.012'); +assert.sameValue(nf3.format('1.2345e-21'), '0.000000000000000000001235'); +assert.sameValue(nf3.format('1.2345e-1000'), '0.000'); const nf4 = new NumberFormat('en-US', { minimumSignificantDigits: 2, @@ -71,6 +76,7 @@ assert.sameValue(nf4.format('1.0'), '1.0'); assert.sameValue(nf4.format('1.00'), '1.0'); assert.sameValue(nf4.format('0.00'), '0.0'); assert.sameValue(nf4.format('.00'), '0.0'); +assert.sameValue(nf4.format('0.000000'), '0.0'); assert.sameValue(nf4.format('1.000000'), '1.0'); assert.sameValue(nf4.format('1.99999'), '2.0');