summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test262/intl402/NumberFormat
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /js/src/tests/test262/intl402/NumberFormat
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests/test262/intl402/NumberFormat')
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/browser.js0
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/builtin.js21
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/casing-numbering-system-options.js29
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-compactDisplay-compact.js46
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-compactDisplay-no-compact.js55
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-default-value.js22
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-locales-arraylike.js25
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-locales-get-tostring.js43
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-locales-hasproperty.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-locales-string.js27
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-locales-toobject.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-no-instanceof.js25
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-notation.js33
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-numberingSystem-order.js46
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-option-read-order.js57
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-options-numberingSystem-invalid.js42
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-options-roundingMode-invalid.js35
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-increment.js19
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-mode.js19
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-priority.js19
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-trailing-zero-display.js19
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters.js35
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-options-toobject.js42
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-order.js30
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-roundingIncrement-invalid.js46
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-roundingIncrement.js52
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-signDisplay-negative.js27
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-signDisplay.js33
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-trailingZeroDisplay-invalid.js33
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-trailingZeroDisplay.js36
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-unit.js65
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/constructor-unitDisplay.js68
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/currency-code-invalid.js29
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/currency-code-well-formed.js24
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/currency-digits.js191
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/currencyDisplay-unit.js42
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/default-minimum-singificant-digits.js23
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/default-options-object-prototype.js24
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/dft-currency-mnfd-range-check-mxfd.js24
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/fraction-digit-options-read-once.js20
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/ignore-invalid-unicode-ext-values.js38
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/instance-proto-and-extensible.js19
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/intl-legacy-constructed-symbol-on-unwrap.js34
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/intl-legacy-constructed-symbol.js20
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/legacy-regexp-statics-not-modified.js21
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/length.js36
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/name.js29
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/numbering-system-options.js64
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prop-desc.js33
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/proto-from-ctor-realm.js60
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/browser.js0
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/builtin.js18
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/constructor/browser.js0
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/constructor/prop-desc.js33
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/constructor/shell.js0
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/constructor/value.js14
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/bound-to-numberformat-instance.js37
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/browser.js0
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/builtin.js33
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/default-value.js25
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-de-DE.js78
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-en-US.js78
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-ja-JP.js78
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-ko-KR.js78
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-zh-TW.js78
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-fraction-digits-precision.js34
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-fraction-digits.js57
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-builtin.js33
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-length.js31
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-name.js28
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-property-order.js18
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-max-min-fraction-significant-digits.js29
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-negative-numbers.js23
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-non-finite-numbers.js45
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-10.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-100.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1000.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-20.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-200.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2000.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-25.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-250.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2500.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-50.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-500.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5000.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-ceil.js34
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-expand.js34
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-floor.js34
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-ceil.js35
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-even.js36
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-expand.js35
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-floor.js35
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-trunc.js35
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-trunc.js34
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-auto.js49
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-less-precision.js49
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-more-precision.js49
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-significant-digits-precision.js34
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/format-significant-digits.js57
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/length.js36
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/name.js31
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/no-instanceof.js26
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-de-DE.js47
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-en-US.js47
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-ja-JP.js47
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-ko-KR.js47
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-zh-TW.js47
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/numbering-systems.js25
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/percent-formatter.js25
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/prop-desc.js39
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/shell.js24
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-de-DE.js62
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-en-US.js62
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ja-JP.js62
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ko-KR.js62
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-zh-TW.js62
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-de-DE.js77
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-en-US.js77
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-ja-JP.js77
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-ko-KR.js77
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-de-DE.js19
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-en-US.js19
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-ja-JP.js19
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-ko-KR.js19
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-zh-TW.js19
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-de-DE.js22
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-en-US.js22
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-ja-JP.js22
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-ko-KR.js22
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-zh-TW.js22
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-rounding.js20
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-zh-TW.js77
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/this-value-not-numberformat.js23
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-de-DE.js71
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-en-US.js71
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-ja-JP.js71
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-ko-KR.js71
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-zh-TW.js71
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/units-invalid.js110
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/units.js27
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-de-DE.js33
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-en-IN.js34
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-en-US.js34
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-de-DE.js35
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-en-IN.js35
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-en-US.js35
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/value-arg-coerced-to-number.js26
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/value-decimal-string.js26
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/format/value-tonumber.js46
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/argument-to-Intlmathematicalvalue-throws.js23
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/browser.js0
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/builtin.js31
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/en-US.js39
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/invoked-as-func.js22
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/length.js16
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/name.js16
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/nan-arguments-throws.js31
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/prop-desc.js22
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/pt-PT.js39
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/shell.js24
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/undefined-arguments-throws.js22
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/x-greater-than-y-not-throws.js49
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/argument-to-Intlmathematicalvalue-throws.js23
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/browser.js0
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/builtin.js31
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/en-US.js67
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/invoked-as-func.js22
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/length.js16
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/name.js16
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/nan-arguments-throws.js31
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/prop-desc.js22
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/shell.js24
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/undefined-arguments-throws.js22
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/x-greater-than-y-not-throws.js49
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/browser.js0
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/default-parameter.js44
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-de-DE.js88
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-en-US.js88
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-ja-JP.js88
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-ko-KR.js88
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-zh-TW.js88
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/length.js16
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/main.js67
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/name.js16
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-de-DE.js94
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-en-US.js94
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-ja-JP.js90
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-ko-KR.js90
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-zh-TW.js90
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/percent-en-US.js38
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/prop-desc.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/shell.js0
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-de-DE.js72
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-en-US.js72
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ja-JP.js72
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ko-KR.js72
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-zh-TW.js72
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-de-DE.js87
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-en-US.js87
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-ja-JP.js87
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-ko-KR.js87
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-de-DE.js55
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-en-US.js55
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-ja-JP.js55
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-ko-KR.js55
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-zh-TW.js55
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-de-DE.js35
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-en-US.js35
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-ja-JP.js35
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-ko-KR.js35
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-zh-TW.js35
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-zh-TW.js87
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/this-value-not-numberformat.js23
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-de-DE.js99
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-en-US.js99
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-ja-JP.js99
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-ko-KR.js99
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-zh-TW.js99
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit.js27
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/value-tonumber.js52
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/prop-desc.js17
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/basic.js45
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/browser.js0
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/builtin.js30
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/compactDisplay.js26
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/length.js34
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/name.js29
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/no-instanceof.js26
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/order.js43
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/prop-desc.js33
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/return-keys-order-default.js49
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/roundingMode.js42
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/shell.js24
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/this-value-not-numberformat.js23
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/shell.js0
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/this-value-numberformat-prototype.js17
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/browser.js0
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/configurable.js35
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/prop-desc.js18
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/shell.js0
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/shell.js0
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/significant-digits-options-get-sequence.js42
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/style-unit.js28
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/subclassing.js30
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/basic.js25
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/browser.js0
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/builtin.js30
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/length.js34
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/name.js29
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/prop-desc.js33
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/shell.js24
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/taint-Object-prototype.js16
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/taint-Object-prototype.js18
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/test-option-currency.js57
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/test-option-currencyDisplay.js16
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/test-option-localeMatcher.js13
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/test-option-roundingPriority-mixed-options.js96
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/test-option-roundingPriority.js18
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/test-option-style.js14
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping-extended.js41
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping.js42
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/this-value-ignored.js37
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/throws-for-currency-style-without-currency-option.js22
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/throws-for-maximumFractionDigits-over-limit.js24
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/throws-for-maximumFractionDigits-under-limit.js24
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/throws-for-minimumFractionDigits-over-limit.js24
-rw-r--r--js/src/tests/test262/intl402/NumberFormat/throws-for-minimumFractionDigits-under-limit.js24
271 files changed, 10926 insertions, 0 deletions
diff --git a/js/src/tests/test262/intl402/NumberFormat/browser.js b/js/src/tests/test262/intl402/NumberFormat/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/browser.js
diff --git a/js/src/tests/test262/intl402/NumberFormat/builtin.js b/js/src/tests/test262/intl402/NumberFormat/builtin.js
new file mode 100644
index 0000000000..6848ae39e9
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/builtin.js
@@ -0,0 +1,21 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+es5id: 11.1_L15
+description: >
+ Tests that Intl.NumberFormat meets the requirements for built-in
+ objects defined by the introduction of chapter 17 of the
+ ECMAScript Language Specification.
+author: Norbert Lindenberg
+---*/
+
+assert.sameValue(Object.prototype.toString.call(Intl.NumberFormat), "[object Function]",
+ "The [[Class]] internal property of a built-in function must be " +
+ "\"Function\".");
+
+assert(Object.isExtensible(Intl.NumberFormat), "Built-in objects must be extensible.");
+
+assert.sameValue(Object.getPrototypeOf(Intl.NumberFormat), Function.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/casing-numbering-system-options.js b/js/src/tests/test262/intl402/NumberFormat/casing-numbering-system-options.js
new file mode 100644
index 0000000000..11572923c6
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/casing-numbering-system-options.js
@@ -0,0 +1,29 @@
+// Copyright 2020 Google Inc, Igalia S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: >
+ Tests that the options numberingSystem are mapped to lower case.
+author: Caio Lima
+features: [Array.prototype.includes]
+---*/
+
+let defaultLocale = new Intl.NumberFormat().resolvedOptions().locale;
+
+let supportedNumberingSystems = ["latn", "arab"].filter(nu =>
+ new Intl.NumberFormat(defaultLocale + "-u-nu-" + nu)
+ .resolvedOptions().numberingSystem === nu
+);
+
+if (supportedNumberingSystems.includes("latn")) {
+ let numberFormat = new Intl.NumberFormat(defaultLocale + "-u-nu-lATn");
+ assert.sameValue(numberFormat.resolvedOptions().numberingSystem, "latn", "Numbering system option should be in lower case");
+}
+
+if (supportedNumberingSystems.includes("arab")) {
+ let numberFormat = new Intl.NumberFormat(defaultLocale + "-u-nu-Arab");
+ assert.sameValue(numberFormat.resolvedOptions().numberingSystem, "arab", "Numbering system option should be in lower case");
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-compactDisplay-compact.js b/js/src/tests/test262/intl402/NumberFormat/constructor-compactDisplay-compact.js
new file mode 100644
index 0000000000..ef5061b87d
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-compactDisplay-compact.js
@@ -0,0 +1,46 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: Checks handling of the compactDisplay option to the NumberFormat constructor.
+info: |
+ InitializeNumberFormat ( numberFormat, locales, options )
+
+ 19. Let compactDisplay be ? GetOption(options, "compactDisplay", "string", « "short", "long" », "short").
+ 20. If notation is "compact", then
+ a. Set numberFormat.[[CompactDisplay]] to compactDisplay.
+
+includes: [compareArray.js]
+features: [Intl.NumberFormat-unified]
+---*/
+
+const values = [
+ [undefined, "short"],
+ ["short"],
+ ["long"],
+];
+
+for (const [value, expected = value] of values) {
+ const callOrder = [];
+ const nf = new Intl.NumberFormat([], {
+ get notation() {
+ callOrder.push("notation");
+ return "compact";
+ },
+ get compactDisplay() {
+ callOrder.push("compactDisplay");
+ return value;
+ }
+ });
+ const resolvedOptions = nf.resolvedOptions();
+ assert.sameValue("compactDisplay" in resolvedOptions, true);
+ assert.sameValue(resolvedOptions.compactDisplay, expected);
+
+ assert.compareArray(callOrder, [
+ "notation",
+ "compactDisplay",
+ ]);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-compactDisplay-no-compact.js b/js/src/tests/test262/intl402/NumberFormat/constructor-compactDisplay-no-compact.js
new file mode 100644
index 0000000000..9f5b1336ad
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-compactDisplay-no-compact.js
@@ -0,0 +1,55 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: Checks handling of the compactDisplay option to the NumberFormat constructor.
+info: |
+ InitializeNumberFormat ( numberFormat, locales, options )
+
+ 19. Let compactDisplay be ? GetOption(options, "compactDisplay", "string", « "short", "long" », "short").
+ 20. If notation is "compact", then
+ a. Set numberFormat.[[CompactDisplay]] to compactDisplay.
+
+includes: [compareArray.js]
+features: [Intl.NumberFormat-unified]
+---*/
+
+const values = [
+ [undefined, "short"],
+ ["short"],
+ ["long"],
+];
+
+const notations = [
+ undefined,
+ "standard",
+ "scientific",
+ "engineering",
+];
+
+for (const notation of notations) {
+ for (const [value, expected = value] of values) {
+ const callOrder = [];
+ const nf = new Intl.NumberFormat([], {
+ get notation() {
+ callOrder.push("notation");
+ return notation;
+ },
+ get compactDisplay() {
+ callOrder.push("compactDisplay");
+ return value;
+ }
+ });
+ const resolvedOptions = nf.resolvedOptions();
+ assert.sameValue("compactDisplay" in resolvedOptions, false);
+ assert.sameValue(resolvedOptions.compactDisplay, undefined);
+
+ assert.compareArray(callOrder, [
+ "notation",
+ "compactDisplay",
+ ]);
+ }
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-default-value.js b/js/src/tests/test262/intl402/NumberFormat/constructor-default-value.js
new file mode 100644
index 0000000000..f92618543d
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-default-value.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2018 Ujjwal Sharma. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: >
+ Tests that the constructor for Intl.NumberFormat uses appropriate default
+ values for its arguments (locales and options).
+---*/
+
+const actual = new Intl.NumberFormat().resolvedOptions();
+const expected = new Intl.NumberFormat([], Object.create(null)).resolvedOptions();
+
+assert.sameValue(actual.locale, expected.locale);
+assert.sameValue(actual.minimumIntegerDigits, expected.minimumIntegerDigits);
+assert.sameValue(actual.minimumFractionDigits, expected.minimumFractionDigits);
+assert.sameValue(actual.maximumFractionDigits, expected.maximumFractionDigits);
+assert.sameValue(actual.numberingSystem, expected.numberingSystem);
+assert.sameValue(actual.style, expected.style);
+assert.sameValue(actual.useGrouping, expected.useGrouping);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-locales-arraylike.js b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-arraylike.js
new file mode 100644
index 0000000000..816bcd2096
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-arraylike.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2018 Ujjwal Sharma. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: >
+ Tests that the Intl.NumberFormat constructor accepts Array-like values for the
+ locales argument and treats them well.
+---*/
+
+const actual = Intl.NumberFormat({
+ length: 1,
+ 0: 'en-US'
+}).resolvedOptions();
+const expected = Intl.NumberFormat(['en-US']).resolvedOptions();
+
+assert.sameValue(actual.locale, expected.locale);
+assert.sameValue(actual.minimumIntegerDigits, expected.minimumIntegerDigits);
+assert.sameValue(actual.minimumFractionDigits, expected.minimumFractionDigits);
+assert.sameValue(actual.maximumFractionDigits, expected.maximumFractionDigits);
+assert.sameValue(actual.numberingSystem, expected.numberingSystem);
+assert.sameValue(actual.style, expected.style);
+assert.sameValue(actual.useGrouping, expected.useGrouping);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-locales-get-tostring.js b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-get-tostring.js
new file mode 100644
index 0000000000..d7bb6422c3
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-get-tostring.js
@@ -0,0 +1,43 @@
+// Copyright (C) 2018 Ujjwal Sharma. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: >
+ Tests that Get(O, P) and ToString(arg) are properly called within the
+ constructor for Intl.NumberFormat
+info: |
+ 9.2.1 CanonicalizeLocaleList ( locales )
+
+ 5. Let len be ? ToLength(? Get(O, "length")).
+
+ 7.a. Let Pk be ToString(k).
+
+ 7.c.i. Let kValue be ? Get(O, Pk).
+---*/
+
+const locales = {
+ length: 8,
+ 1: 'en-US',
+ 3: 'de-DE',
+ 5: 'en-IN',
+ 7: 'en-GB'
+};
+
+const actualLookups = [];
+const expectedLookups = Object.keys(locales);
+
+const handlers = {
+ get(obj, prop) {
+ actualLookups.push(prop);
+ return Reflect.get(...arguments);
+ }
+};
+
+const proxyLocales = new Proxy(locales, handlers);
+
+const nf = new Intl.NumberFormat(proxyLocales);
+
+expectedLookups.forEach(lookup => assert(actualLookups.indexOf(lookup) != -1));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-locales-hasproperty.js b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-hasproperty.js
new file mode 100644
index 0000000000..93784924ae
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-hasproperty.js
@@ -0,0 +1,41 @@
+// Copyright (C) 2018 Ujjwal Sharma. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: >
+ Tests that HasProperty(O, Pk) is properly called within the constructor for
+ Intl.NumberFormat
+info: |
+ 9.2.1 CanonicalizeLocaleList ( locales )
+
+ 7.b. Let kPresent be ? HasProperty(O, Pk).
+---*/
+
+const locales = {
+ length: 8,
+ 1: 'en-US',
+ 3: 'de-DE',
+ 5: 'en-IN',
+ 7: 'en-GB'
+};
+
+const actualLookups = [];
+
+const handlers = {
+ has(obj, prop) {
+ actualLookups.push(prop);
+ return Reflect.has(...arguments);
+ }
+};
+
+const proxyLocales = new Proxy(locales, handlers);
+
+const nf = new Intl.NumberFormat(proxyLocales);
+
+assert.sameValue(actualLookups.length, locales.length);
+for (let index in actualLookups) {
+ assert.sameValue(actualLookups[index], String(index));
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-locales-string.js b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-string.js
new file mode 100644
index 0000000000..b2703b1def
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-string.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2018 Ujjwal Sharma. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: >
+ Tests that passing a string value to the Intl.NumberFormat constructor is
+ equivalent to passing an Array containing the same string value.
+info: |
+ 9.2.1 CanonicalizeLocaleList ( locales )
+
+ 3 .If Type(locales) is String, then
+ a. Let O be CreateArrayFromList(« locales »).
+---*/
+
+const actual = Intl.NumberFormat('en-US').resolvedOptions();
+const expected = Intl.NumberFormat(['en-US']).resolvedOptions();
+
+assert.sameValue(actual.locale, expected.locale);
+assert.sameValue(actual.minimumIntegerDigits, expected.minimumIntegerDigits);
+assert.sameValue(actual.minimumFractionDigits, expected.minimumFractionDigits);
+assert.sameValue(actual.maximumFractionDigits, expected.maximumFractionDigits);
+assert.sameValue(actual.numberingSystem, expected.numberingSystem);
+assert.sameValue(actual.style, expected.style);
+assert.sameValue(actual.useGrouping, expected.useGrouping);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-locales-toobject.js b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-toobject.js
new file mode 100644
index 0000000000..08df0d0580
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-toobject.js
@@ -0,0 +1,41 @@
+// Copyright (C) 2018 Ujjwal Sharma. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: >
+ Tests that Intl.NumberFormat contructor converts the locales argument
+ to an object using `ToObject` (7.1.13).
+info: |
+ 9.2.1 CanonicalizeLocaleList
+
+ 4.a. Let O be ? ToObject(locales).
+---*/
+
+const toObjectResults = [
+ [true, new Boolean(true)],
+ [42, new Number(42)],
+ [{}, {}],
+ [Symbol(), Object(Symbol())]
+];
+
+// Test if ToObject is used to convert primitives to Objects.
+toObjectResults.forEach(pair => {
+ const [value, result] = pair;
+ const actual = new Intl.NumberFormat(value).resolvedOptions();
+ const expected = new Intl.NumberFormat(result).resolvedOptions()
+
+ assert.sameValue(actual.locale, expected.locale);
+ assert.sameValue(actual.minimumIntegerDigits, expected.minimumIntegerDigits);
+ assert.sameValue(actual.minimumFractionDigits, expected.minimumFractionDigits);
+ assert.sameValue(actual.maximumFractionDigits, expected.maximumFractionDigits);
+ assert.sameValue(actual.numberingSystem, expected.numberingSystem);
+ assert.sameValue(actual.style, expected.style);
+ assert.sameValue(actual.useGrouping, expected.useGrouping);
+});
+
+// ToObject throws a TypeError for undefined and null, but it's not called
+// when locales is undefined.
+assert.throws(TypeError, () => new Intl.NumberFormat(null));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-no-instanceof.js b/js/src/tests/test262/intl402/NumberFormat/constructor-no-instanceof.js
new file mode 100644
index 0000000000..fe9f1ac720
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-no-instanceof.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2021 Igalia S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl-numberformat-constructor
+description: >
+ Tests that the Intl.NumberFormat constructor calls
+ OrdinaryHasInstance instead of the instanceof operator which includes a
+ Symbol.hasInstance lookup and call among other things.
+info: >
+ ChainNumberFormat ( numberFormat, newTarget, this )
+ 1. If newTarget is undefined and ? OrdinaryHasInstance(%NumberFormat%, this) is true, then
+ a. Perform ? DefinePropertyOrThrow(this, %Intl%.[[FallbackSymbol]], PropertyDescriptor{
+ [[Value]]: numberFormat, [[Writable]]: false, [[Enumerable]]: false,
+ [[Configurable]]: false }).
+ b. Return this.
+---*/
+
+Object.defineProperty(Intl.NumberFormat, Symbol.hasInstance, {
+ get() { throw new Test262Error(); }
+});
+
+Intl.NumberFormat();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-notation.js b/js/src/tests/test262/intl402/NumberFormat/constructor-notation.js
new file mode 100644
index 0000000000..91dc05937c
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-notation.js
@@ -0,0 +1,33 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: Checks handling of the notation option to the NumberFormat constructor.
+info: |
+ InitializeNumberFormat ( numberFormat, locales, options )
+
+ 16. Let notation be ? GetOption(options, "notation", "string", « "standard", "scientific", "engineering", "compact" », "standard").
+ 17. Set numberFormat.[[Notation]] to notation.
+
+features: [Intl.NumberFormat-unified]
+---*/
+
+const values = [
+ [undefined, "standard"],
+ ["standard"],
+ ["scientific"],
+ ["engineering"],
+ ["compact"],
+];
+
+for (const [value, expected = value] of values) {
+ const nf = new Intl.NumberFormat([], {
+ notation: value,
+ });
+ const resolvedOptions = nf.resolvedOptions();
+ assert.sameValue("notation" in resolvedOptions, true);
+ assert.sameValue(resolvedOptions.notation, expected);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-numberingSystem-order.js b/js/src/tests/test262/intl402/NumberFormat/constructor-numberingSystem-order.js
new file mode 100644
index 0000000000..67ec1db98a
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-numberingSystem-order.js
@@ -0,0 +1,46 @@
+// Copyright 2019 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: >
+ Checks the order of getting "numberingSystem" option in the
+ NumberFormat is between "localeMatcher" and "style" options.
+info: |
+ InitializeNumberFormat ( _numberFormat_, _locales_, _options_ )
+
+ 5. Let _matcher_ be ? GetOption(_options_, `"localeMatcher"`, `"string"`, &laquo; `"lookup"`, `"best fit"` &raquo;, `"best fit"`).
+ ...
+ 7. Let _numberingSystem_ be ? GetOption(_options_, `"numberingSystem"`, `"string"`, *undefined*, *undefined*).
+ ...
+ 17. Let _style_ be ? GetOption(_options_, `"style"`, `"string"`, &laquo; `"decimal"`, `"percent"`, `"currency"` &raquo;, `"decimal"`).
+includes: [compareArray.js]
+---*/
+
+var actual = [];
+
+const options = {
+ get localeMatcher() {
+ actual.push("localeMatcher");
+ return undefined;
+ },
+ get numberingSystem() {
+ actual.push("numberingSystem");
+ return undefined;
+ },
+ get style() {
+ actual.push("style");
+ return undefined;
+ },
+};
+
+const expected = [
+ "localeMatcher",
+ "numberingSystem",
+ "style"
+];
+
+let nf = new Intl.NumberFormat(undefined, options);
+assert.compareArray(actual, expected);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-option-read-order.js b/js/src/tests/test262/intl402/NumberFormat/constructor-option-read-order.js
new file mode 100644
index 0000000000..b7e29dd8cd
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-option-read-order.js
@@ -0,0 +1,57 @@
+// Copyright 2023 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: Checks the order of option read.
+features: [Intl.NumberFormat-v3]
+includes: [compareArray.js]
+---*/
+
+let optionKeys = [
+ // Inside InitializeNumberFormat
+ "localeMatcher",
+ "numberingSystem",
+ // Inside SetNumberFormatUnitOptions
+ "style",
+ "currency",
+ "currencyDisplay",
+ "currencySign",
+ "unit",
+ "unitDisplay",
+ // End of SetNumberFormatUnitOptions
+ // Back to InitializeNumberFormat
+ "notation",
+ // Inside SetNumberFormatDigitOptions
+ "minimumIntegerDigits",
+ "minimumFractionDigits",
+ "maximumFractionDigits",
+ "minimumSignificantDigits",
+ "maximumSignificantDigits",
+ "roundingIncrement",
+ "roundingMode",
+ "roundingPriority",
+ "trailingZeroDisplay",
+ // End of SetNumberFormatDigitOptions
+ // Back to InitializeNumberFormat
+ "compactDisplay",
+ "useGrouping",
+ "signDisplay"
+];
+
+// Use getters to track the order of reading known properties.
+// TODO: Should we use a Proxy to detect *unexpected* property reads?
+let reads = new Array();
+let options = {};
+optionKeys.forEach((key) => {
+ Object.defineProperty(options, key, {
+ get() {
+ reads.push(key);
+ return undefined;
+ },
+ });
+});
+new Intl.NumberFormat(undefined, options);
+assert.compareArray(reads, optionKeys, "Intl.NumberFormat options read order");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-options-numberingSystem-invalid.js b/js/src/tests/test262/intl402/NumberFormat/constructor-options-numberingSystem-invalid.js
new file mode 100644
index 0000000000..40de2cd18d
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-options-numberingSystem-invalid.js
@@ -0,0 +1,42 @@
+// Copyright 2020 André Bargull; Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: >
+ Checks error cases for the options argument to the NumberFormat constructor.
+info: |
+ InitializeNumberFormat ( numberFormat, locales, options )
+
+ ...
+ 8. If numberingSystem is not undefined, then
+ a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
+---*/
+
+/*
+ alphanum = (ALPHA / DIGIT) ; letters and numbers
+ numberingSystem = (3*8alphanum) *("-" (3*8alphanum))
+*/
+const invalidNumberingSystemOptions = [
+ "",
+ "a",
+ "ab",
+ "abcdefghi",
+ "abc-abcdefghi",
+ "!invalid!",
+ "-latn-",
+ "latn-",
+ "latn--",
+ "latn-ca",
+ "latn-ca-",
+ "latn-ca-gregory",
+ "latné",
+ "latn编号",
+];
+for (const numberingSystem of invalidNumberingSystemOptions) {
+ assert.throws(RangeError, function() {
+ new Intl.NumberFormat('en', {numberingSystem});
+ }, `new Intl.NumberFormat("en", {numberingSystem: "${numberingSystem}"}) throws RangeError`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-options-roundingMode-invalid.js b/js/src/tests/test262/intl402/NumberFormat/constructor-options-roundingMode-invalid.js
new file mode 100644
index 0000000000..b4177ef246
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-options-roundingMode-invalid.js
@@ -0,0 +1,35 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-initializenumberformat
+description: Abrupt completion from invalid values for `roundingMode`
+features: [Intl.NumberFormat-v3]
+---*/
+
+assert.throws(RangeError, function() {
+ new Intl.NumberFormat('en', {roundingMode: null});
+}, 'null');
+
+assert.throws(RangeError, function() {
+ new Intl.NumberFormat('en', {roundingMode: 3});
+}, 'number');
+
+assert.throws(RangeError, function() {
+ new Intl.NumberFormat('en', {roundingMode: true});
+}, 'boolean');
+
+assert.throws(RangeError, function() {
+ new Intl.NumberFormat('en', {roundingMode: 'HalfExpand'});
+}, 'invalid string');
+
+var symbol = Symbol('halfExpand');
+assert.throws(TypeError, function() {
+ new Intl.NumberFormat('en', {roundingMode: symbol});
+}, 'Symbol');
+
+var brokenToString = { toString: function() { throw new Test262Error(); } };
+assert.throws(Test262Error, function() {
+ new Intl.NumberFormat('en', {roundingMode: brokenToString});
+}, 'broken `toString` implementation');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-increment.js b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-increment.js
new file mode 100644
index 0000000000..bfe7c9648e
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-increment.js
@@ -0,0 +1,19 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-initializenumberformat
+description: >
+ Exception from accessing the "roundingIncrement" option for the NumberFormat
+ constructor should be propagated to the caller
+features: [Intl.NumberFormat-v3]
+---*/
+
+assert.throws(Test262Error, function() {
+ new Intl.NumberFormat('en', {
+ get roundingIncrement() {
+ throw new Test262Error();
+ }
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-mode.js b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-mode.js
new file mode 100644
index 0000000000..ff13e2c860
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-mode.js
@@ -0,0 +1,19 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-initializenumberformat
+description: >
+ Exception from accessing the "roundingMode" option for the NumberFormat
+ constructor should be propagated to the caller
+features: [Intl.NumberFormat-v3]
+---*/
+
+assert.throws(Test262Error, function() {
+ new Intl.NumberFormat('en', {
+ get roundingMode() {
+ throw new Test262Error();
+ }
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-priority.js b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-priority.js
new file mode 100644
index 0000000000..fd0f55bcac
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-rounding-priority.js
@@ -0,0 +1,19 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-initializenumberformat
+description: >
+ Exception from accessing the "roundingPriority" option for the NumberFormat
+ constructor should be propagated to the caller
+features: [Intl.NumberFormat-v3]
+---*/
+
+assert.throws(Test262Error, function() {
+ new Intl.NumberFormat('en', {
+ get roundingPriority() {
+ throw new Test262Error();
+ }
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-trailing-zero-display.js b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-trailing-zero-display.js
new file mode 100644
index 0000000000..b66f332a2c
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters-trailing-zero-display.js
@@ -0,0 +1,19 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-initializenumberformat
+description: >
+ Exception from accessing the "trailingZeroDisplay" option for the
+ NumberFormat constructor should be propagated to the caller
+features: [Intl.NumberFormat-v3]
+---*/
+
+assert.throws(Test262Error, function() {
+ new Intl.NumberFormat('en', {
+ get trailingZeroDisplay() {
+ throw new Test262Error();
+ }
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters.js b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters.js
new file mode 100644
index 0000000000..70dafd7d34
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters.js
@@ -0,0 +1,35 @@
+// Copyright 2018 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: Checks the propagation of exceptions from the options for the NumberFormat constructor.
+---*/
+
+function CustomError() {}
+
+const options = [
+ "localeMatcher",
+ "numberingSystem",
+ "style",
+ "currency",
+ "currencyDisplay",
+ "minimumIntegerDigits",
+ "minimumFractionDigits",
+ "maximumFractionDigits",
+ "minimumSignificantDigits",
+ "maximumSignificantDigits",
+ "useGrouping",
+];
+
+for (const option of options) {
+ assert.throws(CustomError, () => {
+ new Intl.NumberFormat("en", {
+ get [option]() {
+ throw new CustomError();
+ }
+ });
+ }, `Exception from ${option} getter should be propagated`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-options-toobject.js b/js/src/tests/test262/intl402/NumberFormat/constructor-options-toobject.js
new file mode 100644
index 0000000000..7544ad33fc
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-options-toobject.js
@@ -0,0 +1,42 @@
+// Copyright (C) 2018 Ujjwal Sharma. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: >
+ Tests that Intl.NumberFormat contructor converts the options argument
+ to an object using `ToObject` (7.1.13).
+info: |
+ 11.1.2 InitializeNumberFormat
+
+ 3.a. Let options be ? ToObject(options).
+---*/
+
+const toObjectResults = [
+ [true, new Boolean(true)],
+ [42, new Number(42)],
+ ['foo', new String('foo')],
+ [{}, {}],
+ [Symbol(), Object(Symbol())]
+];
+
+// Test if ToObject is used to convert primitives to Objects.
+toObjectResults.forEach(pair => {
+ const [value, result] = pair;
+ const actual = new Intl.NumberFormat(['en-US'], value).resolvedOptions();
+ const expected = new Intl.NumberFormat(['en-US'], result).resolvedOptions();
+ assert.sameValue(actual.locale, expected.locale);
+ assert.sameValue(actual.minimumIntegerDigits, expected.minimumIntegerDigits);
+ assert.sameValue(actual.minimumFractionDigits, expected.minimumFractionDigits);
+ assert.sameValue(actual.maximumFractionDigits, expected.maximumFractionDigits);
+ assert.sameValue(actual.numberingSystem, expected.numberingSystem);
+ assert.sameValue(actual.style, expected.style);
+ assert.sameValue(actual.useGrouping, expected.useGrouping);
+
+});
+
+// ToObject throws a TypeError for undefined and null, but it's not called
+// when options is undefined.
+assert.throws(TypeError, () => new Intl.NumberFormat(['en-US'], null));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-order.js b/js/src/tests/test262/intl402/NumberFormat/constructor-order.js
new file mode 100644
index 0000000000..92059305f7
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-order.js
@@ -0,0 +1,30 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: Checks handling of the unit option with the currency style.
+info: |
+ SetNumberFormatUnitOptions ( intlObj, options )
+
+ 5. Let currency be ? GetOption(options, "currency", "string", undefined, undefined).
+ 6. If currency is not undefined, then
+ a. If the result of IsWellFormedCurrencyCode(currency) is false, throw a RangeError exception.
+ 7. If style is "currency" and currency is undefined, throw a TypeError exception.
+ ...
+ 10. Let unit be ? GetOption(options, "unit", "string", undefined, undefined).
+ 11. If unit is not undefined, then
+ a. If the result of IsWellFormedUnitIdentifier(unit) is false, throw a RangeError exception.
+ 12. If style is "unit" and unit is undefined, throw a TypeError exception.
+features: [Intl.NumberFormat-unified]
+---*/
+
+assert.throws(TypeError, () => {
+ new Intl.NumberFormat([], { style: "currency", unit: "test" })
+});
+
+assert.throws(RangeError, () => {
+ new Intl.NumberFormat([], { style: "unit", currency: "test" })
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-roundingIncrement-invalid.js b/js/src/tests/test262/intl402/NumberFormat/constructor-roundingIncrement-invalid.js
new file mode 100644
index 0000000000..5822a7f702
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-roundingIncrement-invalid.js
@@ -0,0 +1,46 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-initializenumberformat
+description: Rejects invalid values for roundingIncrement option.
+features: [Intl.NumberFormat-v3]
+---*/
+
+assert.throws(RangeError, function() {
+ new Intl.NumberFormat([], {roundingIncrement: 0});
+}, '0');
+
+assert.throws(RangeError, function() {
+ new Intl.NumberFormat([], {roundingIncrement: 3});
+}, '3');
+
+assert.throws(RangeError, function() {
+ new Intl.NumberFormat([], {roundingIncrement: 4});
+}, '4');
+
+assert.throws(RangeError, function() {
+ new Intl.NumberFormat([], {roundingIncrement: 5000.1});
+}, '5000.1');
+
+assert.throws(RangeError, function() {
+ new Intl.NumberFormat([], {roundingIncrement: 5001});
+}, '5001');
+
+assert.throws(TypeError, function() {
+ new Intl.NumberFormat([], {roundingIncrement: 2, roundingPriority: 'morePrecision'});
+}, '2, roundingType is "morePrecision"');
+
+assert.throws(TypeError, function() {
+ new Intl.NumberFormat([], {roundingIncrement: 2, roundingPriority: 'lessPrecision'});
+}, '2, roundingType is "lessPrecision"');
+
+assert.throws(TypeError, function() {
+ new Intl.NumberFormat([], {roundingIncrement: 2, minimumSignificantDigits: 1});
+}, '2, roundingType is "significantDigits"');
+
+assert.throws(RangeError, function() {
+ new Intl.NumberFormat([], {roundingIncrement: 2, maximumFractionDigits:3 , minimumFractionDigits:2 });
+}, '"maximumFractionDigits" is not equal to "minimumFractionDigits"');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-roundingIncrement.js b/js/src/tests/test262/intl402/NumberFormat/constructor-roundingIncrement.js
new file mode 100644
index 0000000000..3d8522d28a
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-roundingIncrement.js
@@ -0,0 +1,52 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-initializenumberformat
+description: Checks handling of the roundingIncrement option to the NumberFormat constructor.
+includes: [compareArray.js]
+features: [Intl.NumberFormat-v3]
+---*/
+
+const values = [
+ [undefined, 1],
+ [1, 1],
+ [2, 2],
+ [5, 5],
+ [10, 10],
+ [20, 20],
+ [25, 25],
+ [50, 50],
+ [100, 100],
+ [200, 200],
+ [250, 250],
+ [500, 500],
+ [1000, 1000],
+ [2000, 2000],
+ [2500, 2500],
+ [5000, 5000],
+ [true, 1],
+ ["2", 2],
+ [{valueOf: function() { return 5; }}, 5],
+];
+
+for (const [value, expected] of values) {
+ const callOrder = [];
+ const nf = new Intl.NumberFormat([], {
+ get notation() {
+ callOrder.push("notation");
+ return "standard";
+ },
+ get roundingIncrement() {
+ callOrder.push("roundingIncrement");
+ return value;
+ },
+ minimumFractionDigits: 3
+ });
+ const resolvedOptions = nf.resolvedOptions();
+ assert("roundingIncrement" in resolvedOptions, "has property for value " + value);
+ assert.sameValue(resolvedOptions.roundingIncrement, expected);
+
+ assert.compareArray(callOrder, ["notation", "roundingIncrement"]);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-signDisplay-negative.js b/js/src/tests/test262/intl402/NumberFormat/constructor-signDisplay-negative.js
new file mode 100644
index 0000000000..32ad4023c7
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-signDisplay-negative.js
@@ -0,0 +1,27 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-initializenumberformat
+description: Checks handling of the compactDisplay option to the NumberFormat constructor.
+info: |
+ InitializeNumberFormat ( numberFormat, locales, options )
+
+ 32. Let signDisplay be ? GetOption(options, "signDisplay", "string", « "auto", "never", "always", "exceptZero", "negative" », "auto").
+ 33. Set numberFormat.[[SignDisplay]] to signDisplay.
+includes: [propertyHelper.js]
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat([], {
+ signDisplay: 'negative',
+});
+const resolvedOptions = nf.resolvedOptions();
+
+verifyProperty(resolvedOptions, 'signDisplay', {
+ value: 'negative',
+ writable: true,
+ enumerable: true,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-signDisplay.js b/js/src/tests/test262/intl402/NumberFormat/constructor-signDisplay.js
new file mode 100644
index 0000000000..2b458367c4
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-signDisplay.js
@@ -0,0 +1,33 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: Checks handling of the compactDisplay option to the NumberFormat constructor.
+info: |
+ InitializeNumberFormat ( numberFormat, locales, options )
+
+ 23. Let signDisplay be ? GetOption(options, "signDisplay", "string", « "auto", "never", "always", "exceptZero" », "auto").
+ 24. Set numberFormat.[[SignDisplay]] to signDisplay.
+
+features: [Intl.NumberFormat-unified]
+---*/
+
+const values = [
+ [undefined, "auto"],
+ ["auto"],
+ ["never"],
+ ["always"],
+ ["exceptZero"],
+];
+
+for (const [value, expected = value] of values) {
+ const nf = new Intl.NumberFormat([], {
+ signDisplay: value,
+ });
+ const resolvedOptions = nf.resolvedOptions();
+ assert.sameValue("signDisplay" in resolvedOptions, true);
+ assert.sameValue(resolvedOptions.signDisplay, expected);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-trailingZeroDisplay-invalid.js b/js/src/tests/test262/intl402/NumberFormat/constructor-trailingZeroDisplay-invalid.js
new file mode 100644
index 0000000000..6a5f620a2a
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-trailingZeroDisplay-invalid.js
@@ -0,0 +1,33 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-initializenumberformat
+description: Rejects invalid values for trailingZeroDisplay option.
+features: [Intl.NumberFormat-v3]
+---*/
+
+assert.throws(RangeError, function() {
+ new Intl.NumberFormat([], {trailingZeroDisplay: ''});
+}, 'empty string');
+
+assert.throws(RangeError, function() {
+ new Intl.NumberFormat([], {trailingZeroDisplay: 'Auto'});
+}, 'Auto');
+
+assert.throws(RangeError, function() {
+ new Intl.NumberFormat([], {trailingZeroDisplay: 'StripIfInteger'});
+}, 'StripIfInteger');
+
+assert.throws(RangeError, function() {
+ new Intl.NumberFormat([], {trailingZeroDisplay: 'stripifinteger'});
+}, 'stripifinteger');
+
+assert.throws(RangeError, function() {
+ new Intl.NumberFormat([], {trailingZeroDisplay: ' auto'});
+}, '" auto" (with leading space)');
+
+assert.throws(RangeError, function() {
+ new Intl.NumberFormat([], {trailingZeroDisplay: 'auto '});
+}, '"auto " (with trailing space)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-trailingZeroDisplay.js b/js/src/tests/test262/intl402/NumberFormat/constructor-trailingZeroDisplay.js
new file mode 100644
index 0000000000..d474ef4aa3
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-trailingZeroDisplay.js
@@ -0,0 +1,36 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-initializenumberformat
+description: Checks handling of the trailingZeroDisplay option to the NumberFormat constructor.
+includes: [compareArray.js]
+features: [Intl.NumberFormat-v3]
+---*/
+
+const values = [
+ [undefined, "auto"],
+ ["auto", "auto"],
+ ["stripIfInteger", "stripIfInteger"],
+ [{toString: function() { return "stripIfInteger"; }}, "stripIfInteger"],
+];
+
+for (const [value, expected] of values) {
+ const callOrder = [];
+ const nf = new Intl.NumberFormat([], {
+ get roundingIncrement() {
+ callOrder.push("roundingIncrement");
+ return 1;
+ },
+ get trailingZeroDisplay() {
+ callOrder.push("trailingZeroDisplay");
+ return value;
+ }
+ });
+ const resolvedOptions = nf.resolvedOptions();
+ assert("trailingZeroDisplay" in resolvedOptions, "has property for value " + value);
+ assert.sameValue(resolvedOptions.trailingZeroDisplay, expected);
+
+ assert.compareArray(callOrder, ["roundingIncrement", "trailingZeroDisplay"]);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-unit.js b/js/src/tests/test262/intl402/NumberFormat/constructor-unit.js
new file mode 100644
index 0000000000..36f2e8a002
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-unit.js
@@ -0,0 +1,65 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: Checks handling of the unit style.
+includes: [testIntl.js]
+features: [Intl.NumberFormat-unified]
+---*/
+
+assert.throws(TypeError, () => {
+ new Intl.NumberFormat([], {
+ style: "unit",
+ })
+});
+
+for (const unit of ["test", "MILE", "kB"]) {
+ // Throws RangeError for invalid unit identifier.
+ for (const style of [undefined, "decimal", "unit"]) {
+ assert.throws(RangeError, () => {
+ new Intl.NumberFormat([], { style, unit })
+ }, `{ style: ${style}, unit: ${unit} }`);
+ }
+
+ const style = "currency";
+
+ // Throws TypeError because "currency" option is missing.
+ assert.throws(TypeError, () => {
+ new Intl.NumberFormat([], { style, unit })
+ }, `{ style: ${style}, unit: ${unit} }`);
+
+ // Throws RangeError for invalid unit identifier.
+ assert.throws(RangeError, () => {
+ new Intl.NumberFormat([], { style, unit, currency: "USD" })
+ }, `{ style: ${style}, unit: ${unit} }`);
+}
+
+const nf = new Intl.NumberFormat([], {
+ style: "percent",
+});
+assert.sameValue(nf.resolvedOptions().style, "percent");
+assert.sameValue("unit" in nf.resolvedOptions(), false);
+assert.sameValue(nf.resolvedOptions().unit, undefined);
+
+function check(unit) {
+ const nf = new Intl.NumberFormat([], {
+ style: "unit",
+ unit,
+ });
+ const options = nf.resolvedOptions();
+ assert.sameValue(options.style, "unit");
+ assert.sameValue(options.unit, unit);
+}
+
+const units = allSimpleSanctionedUnits();
+
+for (const simpleUnit of units) {
+ check(simpleUnit);
+ for (const simpleUnit2 of units) {
+ check(simpleUnit + "-per-" + simpleUnit2);
+ check(simpleUnit2 + "-per-" + simpleUnit);
+ }
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-unitDisplay.js b/js/src/tests/test262/intl402/NumberFormat/constructor-unitDisplay.js
new file mode 100644
index 0000000000..54b1594aa5
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/constructor-unitDisplay.js
@@ -0,0 +1,68 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: Checks handling of the compactDisplay option to the NumberFormat constructor.
+info: |
+ InitializeNumberFormat ( numberFormat, locales, options )
+
+ 23. Let signDisplay be ? GetOption(options, "signDisplay", "string", « "auto", "never", "always", "exceptZero" », "auto").
+ 24. Set numberFormat.[[SignDisplay]] to signDisplay.
+
+features: [Intl.NumberFormat-unified]
+---*/
+
+const values = [
+ [undefined, "short"],
+ ["short"],
+ ["narrow"],
+ ["long"],
+];
+
+for (const [value, expected = value] of values) {
+ const nf = new Intl.NumberFormat([], {
+ style: "unit",
+ unitDisplay: value,
+ unit: "hour",
+ });
+ const resolvedOptions = nf.resolvedOptions();
+ assert.sameValue("unitDisplay" in resolvedOptions, true);
+ assert.sameValue(resolvedOptions.unitDisplay, expected);
+}
+
+for (const [value, expected = value] of values) {
+ const nf = new Intl.NumberFormat([], {
+ style: "unit",
+ unitDisplay: value,
+ unit: "percent",
+ });
+ const resolvedOptions = nf.resolvedOptions();
+ assert.sameValue("unitDisplay" in resolvedOptions, true);
+ assert.sameValue(resolvedOptions.unitDisplay, expected);
+}
+
+for (const [value] of values) {
+ const nf = new Intl.NumberFormat([], {
+ style: "percent",
+ unitDisplay: value,
+ });
+ const resolvedOptions = nf.resolvedOptions();
+ assert.sameValue("unitDisplay" in resolvedOptions, false);
+ assert.sameValue(resolvedOptions.unitDisplay, undefined);
+}
+
+const invalidValues = [
+ "",
+ "Short",
+ "s",
+ "\u017Fhort",
+];
+
+for (const unitDisplay of invalidValues) {
+ assert.throws(RangeError, () => {
+ new Intl.NumberFormat([], { unitDisplay });
+ });
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/currency-code-invalid.js b/js/src/tests/test262/intl402/NumberFormat/currency-code-invalid.js
new file mode 100644
index 0000000000..22c43ffb18
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/currency-code-invalid.js
@@ -0,0 +1,29 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 6.3.1_b
+description: Tests that invalid currency codes are not accepted.
+author: Norbert Lindenberg
+---*/
+
+var invalidCurrencyCodes = [
+ "",
+ "€",
+ "$",
+ "SFr.",
+ "DM",
+ "KR₩",
+ "702",
+ "ßP",
+ "ınr"
+];
+
+invalidCurrencyCodes.forEach(function (code) {
+ // this must throw an exception for an invalid currency code
+ assert.throws(RangeError, function() {
+ var format = new Intl.NumberFormat(["de-de"], {style: "currency", currency: code});
+ }, "Invalid currency code '" + code + "' was not rejected.");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/currency-code-well-formed.js b/js/src/tests/test262/intl402/NumberFormat/currency-code-well-formed.js
new file mode 100644
index 0000000000..0b76772b1e
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/currency-code-well-formed.js
@@ -0,0 +1,24 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 6.3.1_a
+description: Tests that well-formed currency codes are accepted.
+author: Norbert Lindenberg
+---*/
+
+var wellFormedCurrencyCodes = [
+ "BOB",
+ "EUR",
+ "usd", // currency codes are case-insensitive
+ "XdR",
+ "xTs"
+];
+
+wellFormedCurrencyCodes.forEach(function (code) {
+ // this must not throw an exception for a valid currency code
+ var format = new Intl.NumberFormat(["de-de"], {style: "currency", currency: code});
+ assert.sameValue(format.resolvedOptions().currency, code.toUpperCase(), "Currency " + code + " was not correctly accepted.");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/currency-digits.js b/js/src/tests/test262/intl402/NumberFormat/currency-digits.js
new file mode 100644
index 0000000000..adba633083
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/currency-digits.js
@@ -0,0 +1,191 @@
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.1.1_20_c
+description: >
+ Tests that the number of fractional digits is determined correctly
+ for currencies.
+author: Norbert Lindenberg
+---*/
+
+// data from https://www.currency-iso.org/dam/downloads/lists/list_one.xml, 2017-09-22
+var currencyDigits = {
+ AED: 2,
+ AFN: 2,
+ ALL: 2,
+ AMD: 2,
+ ANG: 2,
+ AOA: 2,
+ ARS: 2,
+ AUD: 2,
+ AWG: 2,
+ AZN: 2,
+ BAM: 2,
+ BBD: 2,
+ BDT: 2,
+ BGN: 2,
+ BHD: 3,
+ BIF: 0,
+ BMD: 2,
+ BND: 2,
+ BOB: 2,
+ BOV: 2,
+ BRL: 2,
+ BSD: 2,
+ BTN: 2,
+ BWP: 2,
+ BYN: 2,
+ BZD: 2,
+ CAD: 2,
+ CDF: 2,
+ CHE: 2,
+ CHF: 2,
+ CHW: 2,
+ CLF: 4,
+ CLP: 0,
+ CNY: 2,
+ COP: 2,
+ COU: 2,
+ CRC: 2,
+ CUC: 2,
+ CUP: 2,
+ CVE: 2,
+ CZK: 2,
+ DJF: 0,
+ DKK: 2,
+ DOP: 2,
+ DZD: 2,
+ EGP: 2,
+ ERN: 2,
+ ETB: 2,
+ EUR: 2,
+ FJD: 2,
+ FKP: 2,
+ GBP: 2,
+ GEL: 2,
+ GHS: 2,
+ GIP: 2,
+ GMD: 2,
+ GNF: 0,
+ GTQ: 2,
+ GYD: 2,
+ HKD: 2,
+ HNL: 2,
+ HRK: 2,
+ HTG: 2,
+ HUF: 2,
+ IDR: 2,
+ ILS: 2,
+ INR: 2,
+ IQD: 3,
+ IRR: 2,
+ ISK: 0,
+ JMD: 2,
+ JOD: 3,
+ JPY: 0,
+ KES: 2,
+ KGS: 2,
+ KHR: 2,
+ KMF: 0,
+ KPW: 2,
+ KRW: 0,
+ KWD: 3,
+ KYD: 2,
+ KZT: 2,
+ LAK: 2,
+ LBP: 2,
+ LKR: 2,
+ LRD: 2,
+ LSL: 2,
+ LYD: 3,
+ MAD: 2,
+ MDL: 2,
+ MGA: 2,
+ MKD: 2,
+ MMK: 2,
+ MNT: 2,
+ MOP: 2,
+ MRO: 2,
+ MUR: 2,
+ MVR: 2,
+ MWK: 2,
+ MXN: 2,
+ MXV: 2,
+ MYR: 2,
+ MZN: 2,
+ NAD: 2,
+ NGN: 2,
+ NIO: 2,
+ NOK: 2,
+ NPR: 2,
+ NZD: 2,
+ OMR: 3,
+ PAB: 2,
+ PEN: 2,
+ PGK: 2,
+ PHP: 2,
+ PKR: 2,
+ PLN: 2,
+ PYG: 0,
+ QAR: 2,
+ RON: 2,
+ RSD: 2,
+ RUB: 2,
+ RWF: 0,
+ SAR: 2,
+ SBD: 2,
+ SCR: 2,
+ SDG: 2,
+ SEK: 2,
+ SGD: 2,
+ SHP: 2,
+ SLL: 2,
+ SOS: 2,
+ SRD: 2,
+ SSP: 2,
+ STD: 2,
+ SVC: 2,
+ SYP: 2,
+ SZL: 2,
+ THB: 2,
+ TJS: 2,
+ TMT: 2,
+ TND: 3,
+ TOP: 2,
+ TRY: 2,
+ TTD: 2,
+ TWD: 2,
+ TZS: 2,
+ UAH: 2,
+ UGX: 0,
+ USD: 2,
+ USN: 2,
+ UYI: 0,
+ UYU: 2,
+ UZS: 2,
+ VEF: 2,
+ VND: 0,
+ VUV: 0,
+ WST: 2,
+ XAF: 0,
+ XCD: 2,
+ XOF: 0,
+ XPF: 0,
+ YER: 2,
+ ZAR: 2,
+ ZMW: 2,
+ ZWL: 2,
+};
+
+Object.getOwnPropertyNames(currencyDigits).forEach(function (currency) {
+ var digits = currencyDigits[currency];
+ var format = Intl.NumberFormat([], {style: "currency", currency: currency});
+ var min = format.resolvedOptions().minimumFractionDigits;
+ var max = format.resolvedOptions().maximumFractionDigits;
+ assert.sameValue(min, digits, "Didn't get correct minimumFractionDigits for currency " + currency + ".");
+ assert.sameValue(max, digits, "Didn't get correct maximumFractionDigits for currency " + currency + ".");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/currencyDisplay-unit.js b/js/src/tests/test262/intl402/NumberFormat/currencyDisplay-unit.js
new file mode 100644
index 0000000000..bc760e490c
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/currencyDisplay-unit.js
@@ -0,0 +1,42 @@
+// Copyright 2018 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-setnumberformatunitoptions
+description: Checks handling of valid values for the numeric option to the NumberFormat constructor.
+info: |
+ SetNumberFormatUnitOptions ( intlObj, options )
+
+ 6. Let currencyDisplay be ? GetOption(options, "currencyDisplay", "string", « "code", "symbol", "narrowSymbol", "name" », "symbol").
+ 11. If style is "currency", then
+ f. Set intlObj.[[CurrencyDisplay]] to currencyDisplay.
+
+features: [Intl.NumberFormat-unified]
+---*/
+
+const validOptions = [
+ [undefined, "symbol"],
+ ["narrowSymbol", "narrowSymbol"],
+ [{ toString() { return "narrowSymbol"; } }, "narrowSymbol"],
+];
+
+for (const [validOption, expected] of validOptions) {
+ const nf = new Intl.NumberFormat([], {
+ "style": "currency",
+ "currency": "EUR",
+ "currencyDisplay": validOption,
+ });
+ const resolvedOptions = nf.resolvedOptions();
+ assert.sameValue(resolvedOptions.currencyDisplay, expected);
+}
+
+for (const [validOption] of validOptions) {
+ const nf = new Intl.NumberFormat([], {
+ "style": "percent",
+ "currencyDisplay": validOption,
+ });
+ const resolvedOptions = nf.resolvedOptions();
+ assert.sameValue(resolvedOptions.currencyDisplay, undefined);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/default-minimum-singificant-digits.js b/js/src/tests/test262/intl402/NumberFormat/default-minimum-singificant-digits.js
new file mode 100644
index 0000000000..a9cab8c641
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/default-minimum-singificant-digits.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2017 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Tests that the default value of minimumSignificantDigits is 1.
+esid: sec-setnfdigitoptions
+---*/
+
+// maximumSignificantDigits needs to be in range from minimumSignificantDigits
+// to 21 (both inclusive). Setting maximumSignificantDigits to 0 will throw a
+// RangeError if the (default) minimumSignificantDigits is at least 1.
+assert.throws(RangeError, function() {
+ Intl.NumberFormat(undefined, {maximumSignificantDigits: 0});
+});
+
+// If nothing is thrown, check that the options are resolved appropriately.
+var res = Intl.NumberFormat(undefined, {maximumSignificantDigits: 1})
+
+assert.sameValue(Object.getPrototypeOf(res), Intl.NumberFormat.prototype, 'result is an instance of NumberFormat')
+assert.sameValue(res.resolvedOptions().minimumSignificantDigits, 1, 'default minimumSignificantDigits')
+assert.sameValue(res.resolvedOptions().maximumSignificantDigits, 1, 'sets maximumSignificantDigits')
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/default-options-object-prototype.js b/js/src/tests/test262/intl402/NumberFormat/default-options-object-prototype.js
new file mode 100644
index 0000000000..8f43d572f5
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/default-options-object-prototype.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2017 Daniel Ehrenberg. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: >
+ Monkey-patching Object.prototype does not change the default
+ options for NumberFormat as a null prototype is used.
+info: |
+ InitializeNumberFormat ( numberFormat, locales, options )
+
+ 1. If _options_ is *undefined*, then
+ 1. Let _options_ be ObjectCreate(*null*).
+---*/
+
+let defaultMaximumFractionDigits =
+ new Intl.NumberFormat("en").resolvedOptions().maximumFractionDigits;
+
+Object.prototype.maximumFractionDigits = 1;
+let formatter = new Intl.NumberFormat("en");
+assert.sameValue(formatter.resolvedOptions().maximumFractionDigits,
+ defaultMaximumFractionDigits);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/dft-currency-mnfd-range-check-mxfd.js b/js/src/tests/test262/intl402/NumberFormat/dft-currency-mnfd-range-check-mxfd.js
new file mode 100644
index 0000000000..3db6686349
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/dft-currency-mnfd-range-check-mxfd.js
@@ -0,0 +1,24 @@
+// Copyright 2017 the V8 project authors. All rights reserved.
+// Copyright 2020 Apple Inc. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+esid: sec-setnfdigitoptions
+description: >
+ When a currency is used in Intl.NumberFormat and minimumFractionDigits is
+ not provided, maximumFractionDigits should be set as provided.
+---*/
+
+assert.sameValue((new Intl.NumberFormat('en', {
+ style: 'currency',
+ currency: 'USD',
+ maximumFractionDigits: 1
+})).resolvedOptions().maximumFractionDigits, 1);
+
+assert.sameValue((new Intl.NumberFormat('en', {
+ style: 'currency',
+ currency: 'CLF',
+ maximumFractionDigits: 3
+})).resolvedOptions().maximumFractionDigits, 3);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/fraction-digit-options-read-once.js b/js/src/tests/test262/intl402/NumberFormat/fraction-digit-options-read-once.js
new file mode 100644
index 0000000000..faf89e8f9d
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/fraction-digit-options-read-once.js
@@ -0,0 +1,20 @@
+// Copyright 2017 the V8 project authors. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+esid: sec-setnfdigitoptions
+description: >
+ The maximum and minimum fraction digits properties should be read from
+ the options bag exactly once from the NumberFormat constructor.
+info: Regression test for https://bugs.chromium.org/p/v8/issues/detail?id=6015
+---*/
+
+var calls = [];
+
+new Intl.NumberFormat("en", { get minimumFractionDigits() { calls.push('minimumFractionDigits') },
+ get maximumFractionDigits() { calls.push('maximumFractionDigits') } });
+assert.sameValue(calls.length, 2);
+assert.sameValue(calls[0], 'minimumFractionDigits');
+assert.sameValue(calls[1], 'maximumFractionDigits');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/ignore-invalid-unicode-ext-values.js b/js/src/tests/test262/intl402/NumberFormat/ignore-invalid-unicode-ext-values.js
new file mode 100644
index 0000000000..01ac841152
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/ignore-invalid-unicode-ext-values.js
@@ -0,0 +1,38 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+es5id: 11.2.3_b
+description: >
+ Tests that Intl.NumberFormat does not accept Unicode locale
+ extension keys and values that are not allowed.
+author: Norbert Lindenberg
+---*/
+
+var locales = ["ja-JP", "zh-Hans-CN", "zh-Hant-TW"];
+var input = 1234567.89;
+
+locales.forEach(function (locale) {
+ var defaultNumberFormat = new Intl.NumberFormat([locale]);
+ var defaultOptions = defaultNumberFormat.resolvedOptions();
+ var defaultOptionsJSON = JSON.stringify(defaultOptions);
+ var defaultLocale = defaultOptions.locale;
+ var defaultFormatted = defaultNumberFormat.format(input);
+
+ var keyValues = {
+ "cu": ["USD", "EUR", "JPY", "CNY", "TWD", "invalid"],
+ "nu": ["native", "traditio", "finance", "invalid"]
+ };
+
+ Object.getOwnPropertyNames(keyValues).forEach(function (key) {
+ keyValues[key].forEach(function (value) {
+ var numberFormat = new Intl.NumberFormat([locale + "-u-" + key + "-" + value]);
+ var options = numberFormat.resolvedOptions();
+ assert.sameValue(options.locale, defaultLocale, "Locale " + options.locale + " is affected by key " + key + "; value " + value + ".");
+ assert.sameValue(JSON.stringify(options), defaultOptionsJSON, "Resolved options " + JSON.stringify(options) + " are affected by key " + key + "; value " + value + ".");
+ assert.sameValue(numberFormat.format(input), defaultFormatted, "Formatted value " + numberFormat.format(input) + " is affected by key " + key + "; value " + value + ".");
+ });
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/instance-proto-and-extensible.js b/js/src/tests/test262/intl402/NumberFormat/instance-proto-and-extensible.js
new file mode 100644
index 0000000000..0a2b3e8999
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/instance-proto-and-extensible.js
@@ -0,0 +1,19 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.1.3
+description: >
+ Tests that objects constructed by Intl.NumberFormat have the
+ specified internal properties.
+author: Norbert Lindenberg
+---*/
+
+var obj = new Intl.NumberFormat();
+
+var actualPrototype = Object.getPrototypeOf(obj);
+assert.sameValue(actualPrototype, Intl.NumberFormat.prototype, "Prototype of object constructed by Intl.NumberFormat isn't Intl.NumberFormat.prototype.");
+
+assert(Object.isExtensible(obj), "Object constructed by Intl.NumberFormat must be extensible.");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/intl-legacy-constructed-symbol-on-unwrap.js b/js/src/tests/test262/intl402/NumberFormat/intl-legacy-constructed-symbol-on-unwrap.js
new file mode 100644
index 0000000000..aac9c4fc1e
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/intl-legacy-constructed-symbol-on-unwrap.js
@@ -0,0 +1,34 @@
+// Copyright 2020 Apple Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-unwrapnumberformat
+description: >
+ Tests that [[FallbackSymbol]]'s [[Description]] is "IntlLegacyConstructedSymbol" if normative optional is implemented.
+author: Yusuke Suzuki
+features: [intl-normative-optional]
+---*/
+
+let object = new Intl.NumberFormat();
+let newObject = Intl.NumberFormat.call(object);
+let symbol = null;
+let error = null;
+try {
+ let proxy = new Proxy(newObject, {
+ get(target, property) {
+ symbol = property;
+ return target[property];
+ }
+ });
+ Intl.NumberFormat.prototype.resolvedOptions.call(proxy);
+} catch (e) {
+ // If normative optional is not implemented, an error will be thrown.
+ error = e;
+ assert(error instanceof TypeError);
+}
+if (error === null) {
+ assert.sameValue(typeof symbol, "symbol");
+ assert.sameValue(symbol.description, "IntlLegacyConstructedSymbol");
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/intl-legacy-constructed-symbol.js b/js/src/tests/test262/intl402/NumberFormat/intl-legacy-constructed-symbol.js
new file mode 100644
index 0000000000..bf038e96ad
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/intl-legacy-constructed-symbol.js
@@ -0,0 +1,20 @@
+// Copyright 2020 Apple Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat
+description: >
+ Tests that [[FallbackSymbol]]'s [[Description]] is "IntlLegacyConstructedSymbol" if normative optional is implemented.
+author: Yusuke Suzuki
+features: [intl-normative-optional]
+---*/
+
+let object = new Intl.NumberFormat();
+let newObject = Intl.NumberFormat.call(object);
+let symbols = Object.getOwnPropertySymbols(newObject);
+if (symbols.length !== 0) {
+ assert.sameValue(symbols.length, 1);
+ assert.sameValue(symbols[0].description, "IntlLegacyConstructedSymbol");
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/legacy-regexp-statics-not-modified.js b/js/src/tests/test262/intl402/NumberFormat/legacy-regexp-statics-not-modified.js
new file mode 100644
index 0000000000..ba010300c2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/legacy-regexp-statics-not-modified.js
@@ -0,0 +1,21 @@
+// Copyright 2013 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.1.1_a
+description: >
+ Tests that constructing a NumberFormat doesn't create or modify
+ unwanted properties on the RegExp constructor.
+author: Norbert Lindenberg
+includes: [testIntl.js]
+---*/
+
+testForUnwantedRegExpChanges(function () {
+ new Intl.NumberFormat("de-DE-u-nu-latn");
+});
+
+testForUnwantedRegExpChanges(function () {
+ new Intl.NumberFormat("de-DE-u-nu-latn", {style: "currency", currency: "EUR"});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/length.js b/js/src/tests/test262/intl402/NumberFormat/length.js
new file mode 100644
index 0000000000..027ddb1783
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/length.js
@@ -0,0 +1,36 @@
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat
+description: >
+ Intl.NumberFormat.length is 0.
+info: |
+ Intl.NumberFormat ( [ locales [ , options ] ] )
+
+ 17 ECMAScript Standard Built-in Objects:
+
+ Every built-in function object, including constructors, has a length
+ property whose value is an integer. Unless otherwise specified, this
+ value is equal to the largest number of named arguments shown in the
+ subclause headings for the function description. Optional parameters
+ (which are indicated with brackets: [ ]) or rest parameters (which
+ are shown using the form «...name») are not included in the default
+ argument count.
+ Unless otherwise specified, the length property of a built-in function
+ object has the attributes { [[Writable]]: false, [[Enumerable]]: false,
+ [[Configurable]]: true }.
+
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(Intl.NumberFormat.length, 0);
+
+verifyProperty(Intl.NumberFormat, 'length', {
+ value: 0,
+ writable: false,
+ enumerable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/name.js b/js/src/tests/test262/intl402/NumberFormat/name.js
new file mode 100644
index 0000000000..aa918694fc
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/name.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2016 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat
+description: >
+ Intl.NumberFormat.name is "NumberFormat".
+info: |
+ 11.2.1 Intl.NumberFormat ([ locales [ , options ]])
+
+ 17 ECMAScript Standard Built-in Objects:
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value
+ is a String.
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Intl.NumberFormat, 'name', {
+ value: 'NumberFormat',
+ writable: false,
+ enumerable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/numbering-system-options.js b/js/src/tests/test262/intl402/NumberFormat/numbering-system-options.js
new file mode 100644
index 0000000000..6c199f9543
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/numbering-system-options.js
@@ -0,0 +1,64 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: >
+ Tests that the options numberingSystem and calendar can be set through
+ either the locale or the options.
+author: Norbert Lindenberg, Daniel Ehrenberg
+---*/
+
+let defaultLocale = new Intl.NumberFormat().resolvedOptions().locale;
+
+let supportedNumberingSystems = ["latn", "arab"].filter(nu =>
+ new Intl.NumberFormat(defaultLocale + "-u-nu-" + nu)
+ .resolvedOptions().numberingSystem === nu
+);
+
+let options = [
+ {key: "nu", property: "numberingSystem", type: "string", values: supportedNumberingSystems},
+];
+
+options.forEach(function (option) {
+ let numberFormat, opt, result;
+
+ // find out which values are supported for a property in the default locale
+ let supportedValues = [];
+ option.values.forEach(function (value) {
+ opt = {};
+ opt[option.property] = value;
+ numberFormat = new Intl.NumberFormat([defaultLocale], opt);
+ result = numberFormat.resolvedOptions()[option.property];
+ if (result !== undefined && supportedValues.indexOf(result) === -1) {
+ supportedValues.push(result);
+ }
+ });
+
+ // verify that the supported values can also be set through the locale
+ supportedValues.forEach(function (value) {
+ numberFormat = new Intl.NumberFormat([defaultLocale + "-u-" + option.key + "-" + value]);
+ result = numberFormat.resolvedOptions()[option.property];
+ assert.sameValue(result, value, "Property " + option.property + " couldn't be set through locale extension key " + option.key + ".");
+ });
+
+ // verify that the options setting overrides the locale setting
+ supportedValues.forEach(function (value) {
+ let otherValue;
+ option.values.forEach(function (possibleValue) {
+ if (possibleValue !== value) {
+ otherValue = possibleValue;
+ }
+ });
+ if (otherValue !== undefined) {
+ opt = {};
+ opt[option.property] = value;
+ numberFormat = new Intl.NumberFormat([defaultLocale + "-u-" + option.key + "-" + otherValue], opt);
+ result = numberFormat.resolvedOptions()[option.property];
+ assert.sameValue(result, value, "Options value for property " + option.property + " doesn't override locale extension key " + option.key + ".");
+ }
+ });
+});
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prop-desc.js
new file mode 100644
index 0000000000..589dbe8e32
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prop-desc.js
@@ -0,0 +1,33 @@
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat-intro
+description: >
+ "NumberFormat" property of Intl.
+info: |
+ Intl.NumberFormat (...)
+
+ 7 Requirements for Standard Built-in ECMAScript Objects
+
+ Unless specified otherwise in this document, the objects, functions, and constructors
+ described in this standard are subject to the generic requirements and restrictions
+ specified for standard built-in ECMAScript objects in the ECMAScript 2018 Language
+ Specification, 9th edition, clause 17, or successor.
+
+ 17 ECMAScript Standard Built-in Objects:
+
+ Every other data property described in clauses 18 through 26 and in Annex B.2 has the
+ attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }
+ unless otherwise specified.
+
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Intl, 'NumberFormat', {
+ writable: true,
+ enumerable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/proto-from-ctor-realm.js b/js/src/tests/test262/intl402/NumberFormat/proto-from-ctor-realm.js
new file mode 100644
index 0000000000..a8e2be5373
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/proto-from-ctor-realm.js
@@ -0,0 +1,60 @@
+// Copyright (C) 2019 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat
+description: Default [[Prototype]] value derived from realm of the NewTarget.
+info: |
+ Intl.NumberFormat ( [ locales [ , options ] ] )
+
+ 1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
+ 2. Let numberFormat be ? OrdinaryCreateFromConstructor(newTarget, "%NumberFormatPrototype%", « ... »).
+ ...
+ 6. Return numberFormat.
+
+ OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] )
+
+ ...
+ 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto).
+ 3. Return ObjectCreate(proto, internalSlotsList).
+
+ GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto )
+
+ ...
+ 3. Let proto be ? Get(constructor, 'prototype').
+ 4. If Type(proto) is not Object, then
+ a. Let realm be ? GetFunctionRealm(constructor).
+ b. Set proto to realm's intrinsic object named intrinsicDefaultProto.
+ 5. Return proto.
+features: [cross-realm, Reflect, Symbol]
+---*/
+
+var other = $262.createRealm().global;
+var newTarget = new other.Function();
+var nf;
+
+newTarget.prototype = undefined;
+nf = Reflect.construct(Intl.NumberFormat, [], newTarget);
+assert.sameValue(Object.getPrototypeOf(nf), other.Intl.NumberFormat.prototype, 'newTarget.prototype is undefined');
+
+newTarget.prototype = null;
+nf = Reflect.construct(Intl.NumberFormat, [], newTarget);
+assert.sameValue(Object.getPrototypeOf(nf), other.Intl.NumberFormat.prototype, 'newTarget.prototype is null');
+
+newTarget.prototype = true;
+nf = Reflect.construct(Intl.NumberFormat, [], newTarget);
+assert.sameValue(Object.getPrototypeOf(nf), other.Intl.NumberFormat.prototype, 'newTarget.prototype is a Boolean');
+
+newTarget.prototype = 'str';
+nf = Reflect.construct(Intl.NumberFormat, [], newTarget);
+assert.sameValue(Object.getPrototypeOf(nf), other.Intl.NumberFormat.prototype, 'newTarget.prototype is a String');
+
+newTarget.prototype = Symbol();
+nf = Reflect.construct(Intl.NumberFormat, [], newTarget);
+assert.sameValue(Object.getPrototypeOf(nf), other.Intl.NumberFormat.prototype, 'newTarget.prototype is a Symbol');
+
+newTarget.prototype = 0;
+nf = Reflect.construct(Intl.NumberFormat, [], newTarget);
+assert.sameValue(Object.getPrototypeOf(nf), other.Intl.NumberFormat.prototype, 'newTarget.prototype is a Number');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/browser.js b/js/src/tests/test262/intl402/NumberFormat/prototype/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/browser.js
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/builtin.js b/js/src/tests/test262/intl402/NumberFormat/prototype/builtin.js
new file mode 100644
index 0000000000..95eef9d6b3
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/builtin.js
@@ -0,0 +1,18 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+es5id: 11.3_L15
+description: >
+ Tests that Intl.NumberFormat.prototype meets the requirements for
+ built-in objects defined by the introduction of chapter 17 of the
+ ECMAScript Language Specification.
+author: Norbert Lindenberg
+---*/
+
+assert(Object.isExtensible(Intl.NumberFormat.prototype), "Built-in objects must be extensible.");
+
+assert.sameValue(Object.getPrototypeOf(Intl.NumberFormat.prototype), Object.prototype,
+ "Built-in prototype objects must have Object.prototype as their prototype.");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/browser.js b/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/browser.js
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/prop-desc.js
new file mode 100644
index 0000000000..ba521fdc55
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/prop-desc.js
@@ -0,0 +1,33 @@
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.constructor
+description: >
+ "constructor" property of Intl.NumberFormat.prototype.
+info: |
+ Intl.NumberFormat.prototype.constructor
+
+ 7 Requirements for Standard Built-in ECMAScript Objects
+
+ Unless specified otherwise in this document, the objects, functions, and constructors
+ described in this standard are subject to the generic requirements and restrictions
+ specified for standard built-in ECMAScript objects in the ECMAScript 2018 Language
+ Specification, 9th edition, clause 17, or successor.
+
+ 17 ECMAScript Standard Built-in Objects:
+
+ Every other data property described in clauses 18 through 26 and in Annex B.2 has the
+ attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }
+ unless otherwise specified.
+
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Intl.NumberFormat.prototype, "constructor", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/shell.js b/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/shell.js
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/value.js b/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/value.js
new file mode 100644
index 0000000000..28cb427436
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/value.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.3.1
+description: >
+ Tests that Intl.NumberFormat.prototype.constructor is the
+ Intl.NumberFormat.
+author: Roozbeh Pournader
+---*/
+
+assert.sameValue(Intl.NumberFormat.prototype.constructor, Intl.NumberFormat, "Intl.NumberFormat.prototype.constructor is not the same as Intl.NumberFormat");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/bound-to-numberformat-instance.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/bound-to-numberformat-instance.js
new file mode 100644
index 0000000000..f1817ba06f
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/bound-to-numberformat-instance.js
@@ -0,0 +1,37 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.3.2_1_c
+description: Tests that format function is bound to its Intl.NumberFormat.
+author: Norbert Lindenberg
+---*/
+
+var numbers = [0, -0, 1, -1, 5.5, 123, -123, -123.45, 123.44501, 0.001234,
+ -0.00000000123, 0.00000000000000000000000000000123, 1.2, 0.0000000012344501,
+ 123445.01, 12344501000000000000000000000000000, -12344501000000000000000000000000000,
+ Infinity, -Infinity, NaN];
+var locales = [undefined, ["de"], ["th-u-nu-thai"], ["en"], ["ja-u-nu-jpanfin"], ["ar-u-nu-arab"]];
+var options = [
+ undefined,
+ {style: "percent"},
+ {style: "currency", currency: "EUR", currencyDisplay: "symbol"},
+ {style: "currency", currency: "IQD", currencyDisplay: "symbol"},
+ {style: "currency", currency: "KMF", currencyDisplay: "symbol"},
+ {style: "currency", currency: "CLF", currencyDisplay: "symbol"},
+ {useGrouping: false, minimumIntegerDigits: 3, minimumFractionDigits: 1, maximumFractionDigits: 3}
+];
+
+locales.forEach(function (locales) {
+ options.forEach(function (options) {
+ var formatObj = new Intl.NumberFormat(locales, options);
+ var formatFunc = formatObj.format;
+ numbers.forEach(function (number) {
+ var referenceFormatted = formatObj.format(number);
+ var formatted = formatFunc(number);
+ assert.sameValue(referenceFormatted, formatted, "format function produces different result than format method for locales " + locales + "; options: " + (options ? JSON.stringify(options) : options) + ".");
+ });
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/browser.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/browser.js
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/builtin.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/builtin.js
new file mode 100644
index 0000000000..6e264f8d26
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/builtin.js
@@ -0,0 +1,33 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+es5id: 11.3.2_L15
+description: >
+ Tests that the getter for Intl.NumberFormat.prototype.format
+ meets the requirements for built-in objects defined by the
+ introduction of chapter 17 of the ECMAScript Language
+ Specification.
+author: Norbert Lindenberg
+includes: [isConstructor.js]
+features: [Reflect.construct]
+---*/
+
+var formatFn = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format").get;
+
+assert.sameValue(Object.prototype.toString.call(formatFn), "[object Function]",
+ "The [[Class]] internal property of a built-in function must be " +
+ "\"Function\".");
+
+assert(Object.isExtensible(formatFn),
+ "Built-in objects must be extensible.");
+
+assert.sameValue(Object.getPrototypeOf(formatFn), Function.prototype);
+
+assert.sameValue(formatFn.hasOwnProperty("prototype"), false,
+ "Built-in functions that aren't constructors must not have a prototype property.");
+
+assert.sameValue(isConstructor(formatFn), false,
+ "Built-in functions don't implement [[Construct]] unless explicitly specified.");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/default-value.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/default-value.js
new file mode 100644
index 0000000000..b4ee1e8fde
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/default-value.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2018 Ujjwal Sharma. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-number-format-functions
+description: >
+ Tests that the default value for the argument of
+ Intl.NumberFormat.prototype.format (value) is undefined.
+info: |
+ 11.1.4 Number Format Functions
+
+ 3. If value is not provided, let value be undefined.
+ 4. Let x be ? ToNumber(value).
+---*/
+
+const nf = new Intl.NumberFormat();
+
+// In most locales this is string "NaN", but there are exceptions, cf. "ليس رقم"
+// in Arabic, "epäluku" in Finnish, "не число" in Russian, "son emas" in Uzbek etc.
+const resultNaN = nf.format(NaN);
+
+assert.sameValue(nf.format(), resultNaN);
+assert.sameValue(nf.format(undefined), resultNaN);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-de-DE.js
new file mode 100644
index 0000000000..8c70c5e94a
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-de-DE.js
@@ -0,0 +1,78 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the engineering and scientific notations.
+locale: [de-DE]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ 0.000345,
+ "345E-6",
+ "3,45E-4",
+ ],
+ [
+ 0.345,
+ "345E-3",
+ "3,45E-1",
+ ],
+ [
+ 3.45,
+ "3,45E0",
+ "3,45E0",
+ ],
+ [
+ 34.5,
+ "34,5E0",
+ "3,45E1",
+ ],
+ [
+ 543,
+ "543E0",
+ "5,43E2",
+ ],
+ [
+ 5430,
+ "5,43E3",
+ "5,43E3",
+ ],
+ [
+ 543000,
+ "543E3",
+ "5,43E5",
+ ],
+ [
+ 543211.1,
+ "543,211E3",
+ "5,432E5",
+ ],
+ [
+ -Infinity,
+ "-∞",
+ "-∞",
+ ],
+ [
+ Infinity,
+ "∞",
+ "∞",
+ ],
+ [
+ NaN,
+ "NaN",
+ "NaN",
+ ],
+];
+
+for (const [number, engineering, scientific] of tests) {
+ const nfEngineering = (new Intl.NumberFormat("de-DE", { notation: "engineering" }));
+ assert.sameValue(nfEngineering.format(number), engineering);
+ const nfScientific = (new Intl.NumberFormat("de-DE", { notation: "scientific" }));
+ assert.sameValue(nfScientific.format(number), scientific);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-en-US.js
new file mode 100644
index 0000000000..5d8c94ce9a
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-en-US.js
@@ -0,0 +1,78 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the engineering and scientific notations.
+locale: [en-US]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ 0.000345,
+ "345E-6",
+ "3.45E-4",
+ ],
+ [
+ 0.345,
+ "345E-3",
+ "3.45E-1",
+ ],
+ [
+ 3.45,
+ "3.45E0",
+ "3.45E0",
+ ],
+ [
+ 34.5,
+ "34.5E0",
+ "3.45E1",
+ ],
+ [
+ 543,
+ "543E0",
+ "5.43E2",
+ ],
+ [
+ 5430,
+ "5.43E3",
+ "5.43E3",
+ ],
+ [
+ 543000,
+ "543E3",
+ "5.43E5",
+ ],
+ [
+ 543211.1,
+ "543.211E3",
+ "5.432E5",
+ ],
+ [
+ -Infinity,
+ "-∞",
+ "-∞",
+ ],
+ [
+ Infinity,
+ "∞",
+ "∞",
+ ],
+ [
+ NaN,
+ "NaN",
+ "NaN",
+ ],
+];
+
+for (const [number, engineering, scientific] of tests) {
+ const nfEngineering = (new Intl.NumberFormat("en-US", { notation: "engineering" }));
+ assert.sameValue(nfEngineering.format(number), engineering);
+ const nfScientific = (new Intl.NumberFormat("en-US", { notation: "scientific" }));
+ assert.sameValue(nfScientific.format(number), scientific);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-ja-JP.js
new file mode 100644
index 0000000000..85dd68d736
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-ja-JP.js
@@ -0,0 +1,78 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the engineering and scientific notations.
+locale: [ja-JP]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ 0.000345,
+ "345E-6",
+ "3.45E-4",
+ ],
+ [
+ 0.345,
+ "345E-3",
+ "3.45E-1",
+ ],
+ [
+ 3.45,
+ "3.45E0",
+ "3.45E0",
+ ],
+ [
+ 34.5,
+ "34.5E0",
+ "3.45E1",
+ ],
+ [
+ 543,
+ "543E0",
+ "5.43E2",
+ ],
+ [
+ 5430,
+ "5.43E3",
+ "5.43E3",
+ ],
+ [
+ 543000,
+ "543E3",
+ "5.43E5",
+ ],
+ [
+ 543211.1,
+ "543.211E3",
+ "5.432E5",
+ ],
+ [
+ -Infinity,
+ "-∞",
+ "-∞",
+ ],
+ [
+ Infinity,
+ "∞",
+ "∞",
+ ],
+ [
+ NaN,
+ "NaN",
+ "NaN",
+ ],
+];
+
+for (const [number, engineering, scientific] of tests) {
+ const nfEngineering = (new Intl.NumberFormat("ja-JP", { notation: "engineering" }));
+ assert.sameValue(nfEngineering.format(number), engineering);
+ const nfScientific = (new Intl.NumberFormat("ja-JP", { notation: "scientific" }));
+ assert.sameValue(nfScientific.format(number), scientific);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-ko-KR.js
new file mode 100644
index 0000000000..23b5632f0b
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-ko-KR.js
@@ -0,0 +1,78 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the engineering and scientific notations.
+locale: [ko-KR]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ 0.000345,
+ "345E-6",
+ "3.45E-4",
+ ],
+ [
+ 0.345,
+ "345E-3",
+ "3.45E-1",
+ ],
+ [
+ 3.45,
+ "3.45E0",
+ "3.45E0",
+ ],
+ [
+ 34.5,
+ "34.5E0",
+ "3.45E1",
+ ],
+ [
+ 543,
+ "543E0",
+ "5.43E2",
+ ],
+ [
+ 5430,
+ "5.43E3",
+ "5.43E3",
+ ],
+ [
+ 543000,
+ "543E3",
+ "5.43E5",
+ ],
+ [
+ 543211.1,
+ "543.211E3",
+ "5.432E5",
+ ],
+ [
+ -Infinity,
+ "-∞",
+ "-∞",
+ ],
+ [
+ Infinity,
+ "∞",
+ "∞",
+ ],
+ [
+ NaN,
+ "NaN",
+ "NaN",
+ ],
+];
+
+for (const [number, engineering, scientific] of tests) {
+ const nfEngineering = (new Intl.NumberFormat("ko-KR", { notation: "engineering" }));
+ assert.sameValue(nfEngineering.format(number), engineering);
+ const nfScientific = (new Intl.NumberFormat("ko-KR", { notation: "scientific" }));
+ assert.sameValue(nfScientific.format(number), scientific);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-zh-TW.js
new file mode 100644
index 0000000000..5f4cacbb0b
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-zh-TW.js
@@ -0,0 +1,78 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the engineering and scientific notations.
+locale: [zh-TW]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ 0.000345,
+ "345E-6",
+ "3.45E-4",
+ ],
+ [
+ 0.345,
+ "345E-3",
+ "3.45E-1",
+ ],
+ [
+ 3.45,
+ "3.45E0",
+ "3.45E0",
+ ],
+ [
+ 34.5,
+ "34.5E0",
+ "3.45E1",
+ ],
+ [
+ 543,
+ "543E0",
+ "5.43E2",
+ ],
+ [
+ 5430,
+ "5.43E3",
+ "5.43E3",
+ ],
+ [
+ 543000,
+ "543E3",
+ "5.43E5",
+ ],
+ [
+ 543211.1,
+ "543.211E3",
+ "5.432E5",
+ ],
+ [
+ -Infinity,
+ "-∞",
+ "-∞",
+ ],
+ [
+ Infinity,
+ "∞",
+ "∞",
+ ],
+ [
+ NaN,
+ "非數值",
+ "非數值",
+ ],
+];
+
+for (const [number, engineering, scientific] of tests) {
+ const nfEngineering = (new Intl.NumberFormat("zh-TW", { notation: "engineering" }));
+ assert.sameValue(nfEngineering.format(number), engineering);
+ const nfScientific = (new Intl.NumberFormat("zh-TW", { notation: "scientific" }));
+ assert.sameValue(nfScientific.format(number), scientific);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-fraction-digits-precision.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-fraction-digits-precision.js
new file mode 100644
index 0000000000..8b7870f019
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-fraction-digits-precision.js
@@ -0,0 +1,34 @@
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.3.2_TRF
+description: >
+ Tests that the digits are determined correctly when specifying
+ pre/post decimal digits.
+author: Norbert Lindenberg
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale,
+ "ar", "de", "th", "ja"
+];
+var numberingSystems = [
+ "arab",
+ "latn",
+ "thai",
+ "hanidec"
+];
+var testData = {
+ // Ref tc39/ecma402#128
+ "12344501000000000000000000000000000": "12344501000000000000000000000000000.0",
+ "-12344501000000000000000000000000000": "-12344501000000000000000000000000000.0"
+};
+
+testNumberFormat(locales, numberingSystems,
+ {useGrouping: false, minimumIntegerDigits: 3, minimumFractionDigits: 1, maximumFractionDigits: 3},
+ testData);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-fraction-digits.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-fraction-digits.js
new file mode 100644
index 0000000000..cb9c20ad6e
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-fraction-digits.js
@@ -0,0 +1,57 @@
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.3.2_TRF
+description: >
+ Tests that the digits are determined correctly when specifying
+ pre/post decimal digits.
+author: Norbert Lindenberg
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale,
+ "ar", "de", "th", "ja"
+];
+var numberingSystems = [
+ "arab",
+ "latn",
+ "thai",
+ "hanidec"
+];
+var testData = {
+ "0": "000.0",
+ "-0": "-000.0",
+ "123": "123.0",
+ "-123": "-123.0",
+ "12345": "12345.0",
+ "-12345": "-12345.0",
+ "123.45": "123.45",
+ "-123.45": "-123.45",
+ "123.444499": "123.444",
+ "-123.444499": "-123.444",
+ "123.444500": "123.445",
+ "-123.444500": "-123.445",
+ "123.44501": "123.445",
+ "-123.44501": "-123.445",
+ "0.001234": "000.001",
+ "-0.001234": "-000.001",
+ "0.00000000123": "000.0",
+ "-0.00000000123": "-000.0",
+ "0.00000000000000000000000000000123": "000.0",
+ "-0.00000000000000000000000000000123": "-000.0",
+ "1.2": "001.2",
+ "-1.2": "-001.2",
+ "0.0000000012344501": "000.0",
+ "-0.0000000012344501": "-000.0",
+ "123445.01": "123445.01",
+ "-123445.01": "-123445.01",
+};
+
+testNumberFormat(locales, numberingSystems,
+ {useGrouping: false, minimumIntegerDigits: 3, minimumFractionDigits: 1, maximumFractionDigits: 3},
+ testData);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-builtin.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-builtin.js
new file mode 100644
index 0000000000..55f0ce7dd5
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-builtin.js
@@ -0,0 +1,33 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+es5id: 11.3.2_1_a_L15
+description: >
+ Tests that the function returned by
+ Intl.NumberFormat.prototype.format meets the requirements for
+ built-in objects defined by the introduction of chapter 17 of the
+ ECMAScript Language Specification.
+author: Norbert Lindenberg
+includes: [isConstructor.js]
+features: [Reflect.construct]
+---*/
+
+var formatFn = new Intl.NumberFormat().format;
+
+assert.sameValue(Object.prototype.toString.call(formatFn), "[object Function]",
+ "The [[Class]] internal property of a built-in function must be " +
+ "\"Function\".");
+
+assert(Object.isExtensible(formatFn),
+ "Built-in objects must be extensible.");
+
+assert.sameValue(Object.getPrototypeOf(formatFn), Function.prototype);
+
+assert.sameValue(formatFn.hasOwnProperty("prototype"), false,
+ "Built-in functions that aren't constructors must not have a prototype property.");
+
+assert.sameValue(isConstructor(formatFn), false,
+ "Built-in functions don't implement [[Construct]] unless explicitly specified.");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-length.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-length.js
new file mode 100644
index 0000000000..b2884e9e0d
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-length.js
@@ -0,0 +1,31 @@
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ The length of the bound Number Format function is 1.
+info: |
+ get Intl.NumberFormat.prototype.format
+
+ ...
+ 4. If nf.[[BoundFormat]] is undefined, then
+ a. Let F be a new built-in function object as defined in Number Format Functions (11.1.4).
+ b. Let bf be BoundFunctionCreate(F, nf, « »).
+ c. Perform ! DefinePropertyOrThrow(bf, "length", PropertyDescriptor {[[Value]]: 1,
+ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true}).
+ ...
+
+includes: [propertyHelper.js]
+---*/
+
+var formatFn = new Intl.NumberFormat().format;
+
+verifyProperty(formatFn, "length", {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-name.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-name.js
new file mode 100644
index 0000000000..4e4805928e
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-name.js
@@ -0,0 +1,28 @@
+// Copyright (C) 2016 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat.prototype.format
+description: >
+ The bound NumberFormat format function is an anonymous function.
+info: |
+ 11.4.3 get Intl.NumberFormat.prototype.compare
+
+ 17 ECMAScript Standard Built-in Objects:
+ Every built-in function object, including constructors, has a `name`
+ property whose value is a String. Functions that are identified as
+ anonymous functions use the empty string as the value of the `name`
+ property.
+ Unless otherwise specified, the `name` property of a built-in function
+ object has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*,
+ [[Configurable]]: *true* }.
+includes: [propertyHelper.js]
+---*/
+
+var formatFn = new Intl.NumberFormat().format;
+
+verifyProperty(formatFn, "name", {
+ value: "", writable: false, enumerable: false, configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-property-order.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-property-order.js
new file mode 100644
index 0000000000..91b4884286
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-property-order.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2020 ExE Boss. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-createbuiltinfunction
+description: NumberFormat bound format function property order
+info: |
+ Set order: "length", "name"
+includes: [compareArray.js]
+---*/
+
+var formatFn = new Intl.NumberFormat().format;
+
+assert.compareArray(
+ Object.getOwnPropertyNames(formatFn),
+ ['length', 'name']
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-max-min-fraction-significant-digits.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-max-min-fraction-significant-digits.js
new file mode 100644
index 0000000000..f1b2963852
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-max-min-fraction-significant-digits.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Tests that the digits are determined correctly when specifying at same time «"minimumFractionDigits", "maximumFractionDigits", "minimumSignificantDigits", "maximumSignificantDigits"»
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [new Intl.NumberFormat().resolvedOptions().locale, "ar", "de", "th", "ja"];
+var numberingSystems = ["latn", "arab", "thai", "hanidec"];
+
+var nfTestMatrix = [
+ // mnfd & mxfd > mnsd & mxsd
+ [{ useGrouping: false, minimumFractionDigits: 1, maximumFractionDigits: 4, minimumSignificantDigits: 1, maximumSignificantDigits: 2 }, { 1.23456: "1.2" }],
+ [{ useGrouping: false, minimumFractionDigits: 2, maximumFractionDigits: 4, minimumSignificantDigits: 1, maximumSignificantDigits: 2 }, { 1.23456: "1.2" }],
+ // mnfd & mxfd ∩ mnsd & mxsd
+ [{ useGrouping: false, minimumFractionDigits: 2, maximumFractionDigits: 4, minimumSignificantDigits: 2, maximumSignificantDigits: 3 }, { 1.23456: "1.23" }],
+ // mnfd & mxfd < mnsd & mxsd
+ [{ useGrouping: false, minimumFractionDigits: 1, maximumFractionDigits: 2, minimumSignificantDigits: 1, maximumSignificantDigits: 4}, { 1.23456: "1.235" }],
+ [{ useGrouping: false, minimumFractionDigits: 1, maximumFractionDigits: 2, minimumSignificantDigits: 2, maximumSignificantDigits: 4}, { 1.23456: "1.235" }],
+];
+
+nfTestMatrix.forEach((nfTestValues)=>{
+ testNumberFormat(locales, numberingSystems, ...nfTestValues)
+})
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-negative-numbers.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-negative-numbers.js
new file mode 100644
index 0000000000..f572d31997
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-negative-numbers.js
@@ -0,0 +1,23 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.3.2_FN_1
+description: >
+ Tests that Intl.NumberFormat.prototype.format doesn't treat all
+ numbers as negative.
+info: |
+ PartitionNumberPattern ( numberFormat, x )
+ 1. If x is not NaN and x < 0 or _x_ is -0, then
+ a. Let _x_ be -_x_.
+ b. Let _pattern_ be _numberFormat_.[[NegativePattern]].
+author: Roozbeh Pournader
+---*/
+
+var formatter = new Intl.NumberFormat();
+
+assert.notSameValue(formatter.format(1), formatter.format(-1), 'Intl.NumberFormat is formatting 1 and -1 the same way.');
+
+assert.notSameValue(formatter.format(0), formatter.format(-0), 'Intl.NumberFormat is formatting 0 and -0 the same way.');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-non-finite-numbers.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-non-finite-numbers.js
new file mode 100644
index 0000000000..d6dcae7b65
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-non-finite-numbers.js
@@ -0,0 +1,45 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.3.2_FN_2
+description: >
+ Tests that Intl.NumberFormat.prototype.format handles NaN,
+ Infinity, and -Infinity properly.
+author: Roozbeh Pournader
+---*/
+
+// FIXME: We are only listing Numeric_Type=Decimal. May need to add more
+// when the spec clarifies. Current as of Unicode 6.1.
+var hasUnicodeDigits = new RegExp('.*([' +
+ '0-9\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F' +
+ '\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF' +
+ '\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0E50-\u0E59\u0ED0-\u0ED9' +
+ '\u0F20-\u0F29\u1040-\u1049\u1090-\u1099\u17E0-\u17E9\u1810-\u1819' +
+ '\u1946-\u194F\u19D0-\u19D9\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59' +
+ '\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\uA620-\uA629\uA8D0-\uA8D9' +
+ '\uA900-\uA909\uA9D0-\uA9D9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19' +
+ ']|' +
+ '\uD801[\uDCA0-\uDCA9]|' +
+ '\uD804[\uDC66-\uDC6F\uDCF0-\uDCF9\uDD36-\uDD3F\uDDD0-\uDDD9]|' +
+ '\uD805[\uDEC0-\uDEC9]|' +
+ '\uD835[\uDFCE-\uDFFF])');
+
+var formatter = new Intl.NumberFormat();
+var formattedNaN = formatter.format(NaN);
+var formattedInfinity = formatter.format(Infinity);
+var formattedNegativeInfinity = formatter.format(-Infinity);
+
+assert.notSameValue(formattedNaN, formattedInfinity, 'Intl.NumberFormat formats NaN and Infinity the same way.');
+
+assert.notSameValue(formattedNaN, formattedNegativeInfinity, 'Intl.NumberFormat formats NaN and negative Infinity the same way.');
+
+assert.notSameValue(formattedInfinity, formattedNegativeInfinity, 'Intl.NumberFormat formats Infinity and negative Infinity the same way.');
+
+assert.sameValue(hasUnicodeDigits.test(formattedNaN), false, 'Intl.NumberFormat formats NaN using a digit.');
+
+assert.sameValue(hasUnicodeDigits.test(formattedInfinity), false, 'Intl.NumberFormat formats Infinity using a digit.');
+
+assert.sameValue(hasUnicodeDigits.test(formattedNegativeInfinity), false, 'Intl.NumberFormat formats negative Infinity using a digit.');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1.js
new file mode 100644
index 0000000000..6b0b209be0
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1.js
@@ -0,0 +1,41 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: When set to `1`, roundingIncrement is correctly applied
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 1, maximumFractionDigits: 1},
+ {
+ '1.100': '1.1',
+ '1.125': '1.1',
+ '1.150': '1.2',
+ '1.175': '1.2',
+ '1.200': '1.2',
+ }
+);
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 1, maximumFractionDigits: 2},
+ {
+ '1.0100': '1.01',
+ '1.0125': '1.01',
+ '1.0150': '1.02',
+ '1.0175': '1.02',
+ '1.0200': '1.02',
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-10.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-10.js
new file mode 100644
index 0000000000..efb5a54317
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-10.js
@@ -0,0 +1,41 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: When set to `10`, roundingIncrement is correctly applied
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 10, maximumFractionDigits: 2, minimumFractionDigits: 2},
+ {
+ '1.100': '1.10',
+ '1.125': '1.10',
+ '1.150': '1.20',
+ '1.175': '1.20',
+ '1.200': '1.20',
+ }
+);
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 10, maximumFractionDigits: 3, minimumFractionDigits: 3},
+ {
+ '1.0100': '1.010',
+ '1.0125': '1.010',
+ '1.0150': '1.020',
+ '1.0175': '1.020',
+ '1.0200': '1.020',
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-100.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-100.js
new file mode 100644
index 0000000000..5bd2902968
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-100.js
@@ -0,0 +1,41 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: When set to `100`, roundingIncrement is correctly applied
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 100, maximumFractionDigits: 3, minimumFractionDigits: 3},
+ {
+ '1.100': '1.100',
+ '1.125': '1.100',
+ '1.150': '1.200',
+ '1.175': '1.200',
+ '1.200': '1.200',
+ }
+);
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 100, maximumFractionDigits: 4, minimumFractionDigits: 4},
+ {
+ '1.0100': '1.0100',
+ '1.0125': '1.0100',
+ '1.0150': '1.0200',
+ '1.0175': '1.0200',
+ '1.0200': '1.0200',
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1000.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1000.js
new file mode 100644
index 0000000000..d3bdff64b5
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-1000.js
@@ -0,0 +1,41 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: When set to `1000`, roundingIncrement is correctly applied
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 1000, maximumFractionDigits: 4, minimumFractionDigits: 4},
+ {
+ '1.100': '1.1000',
+ '1.125': '1.1000',
+ '1.150': '1.2000',
+ '1.175': '1.2000',
+ '1.200': '1.2000',
+ }
+);
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 1000, maximumFractionDigits: 5, minimumFractionDigits: 5},
+ {
+ '1.0100': '1.01000',
+ '1.0125': '1.01000',
+ '1.0150': '1.02000',
+ '1.0175': '1.02000',
+ '1.0200': '1.02000',
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2.js
new file mode 100644
index 0000000000..97cc2832c9
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2.js
@@ -0,0 +1,41 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: When set to `2`, roundingIncrement is correctly applied
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 2, maximumFractionDigits: 1, minimumFractionDigits: 1},
+ {
+ '1.20': '1.2',
+ '1.25': '1.2',
+ '1.30': '1.4',
+ '1.35': '1.4',
+ '1.40': '1.4',
+ }
+);
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 2, maximumFractionDigits: 2, minimumFractionDigits: 2},
+ {
+ '1.020': '1.02',
+ '1.025': '1.02',
+ '1.030': '1.04',
+ '1.035': '1.04',
+ '1.040': '1.04',
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-20.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-20.js
new file mode 100644
index 0000000000..68d2725e74
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-20.js
@@ -0,0 +1,41 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: When set to `20`, roundingIncrement is correctly applied
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 20, maximumFractionDigits: 2, minimumFractionDigits: 2},
+ {
+ '1.20': '1.20',
+ '1.25': '1.20',
+ '1.30': '1.40',
+ '1.35': '1.40',
+ '1.40': '1.40',
+ }
+);
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 20, maximumFractionDigits: 3, minimumFractionDigits: 3},
+ {
+ '1.020': '1.020',
+ '1.025': '1.020',
+ '1.030': '1.040',
+ '1.035': '1.040',
+ '1.040': '1.040',
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-200.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-200.js
new file mode 100644
index 0000000000..428fc583b3
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-200.js
@@ -0,0 +1,41 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: When set to `200`, roundingIncrement is correctly applied
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 200, maximumFractionDigits: 3, minimumFractionDigits: 3},
+ {
+ '1.20': '1.200',
+ '1.25': '1.200',
+ '1.30': '1.400',
+ '1.35': '1.400',
+ '1.40': '1.400',
+ }
+);
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 200, maximumFractionDigits: 4, minimumFractionDigits: 4},
+ {
+ '1.020': '1.0200',
+ '1.025': '1.0200',
+ '1.030': '1.0400',
+ '1.035': '1.0400',
+ '1.040': '1.0400',
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2000.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2000.js
new file mode 100644
index 0000000000..987c6b30fc
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2000.js
@@ -0,0 +1,41 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: When set to `2000`, roundingIncrement is correctly applied
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 2000, maximumFractionDigits: 4, minimumFractionDigits: 4},
+ {
+ '1.20': '1.2000',
+ '1.25': '1.2000',
+ '1.30': '1.4000',
+ '1.35': '1.4000',
+ '1.40': '1.4000',
+ }
+);
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 2000, maximumFractionDigits: 5, minimumFractionDigits: 5},
+ {
+ '1.020': '1.02000',
+ '1.025': '1.02000',
+ '1.030': '1.04000',
+ '1.035': '1.04000',
+ '1.040': '1.04000',
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-25.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-25.js
new file mode 100644
index 0000000000..a54f963c3e
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-25.js
@@ -0,0 +1,41 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: When set to `25`, roundingIncrement is correctly applied
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 25, maximumFractionDigits: 2, minimumFractionDigits: 2},
+ {
+ '1.2500': '1.25',
+ '1.3125': '1.25',
+ '1.3750': '1.50',
+ '1.4375': '1.50',
+ '1.5000': '1.50',
+ }
+);
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 25, maximumFractionDigits: 3, minimumFractionDigits: 3},
+ {
+ '1.02500': '1.025',
+ '1.03125': '1.025',
+ '1.03750': '1.050',
+ '1.04375': '1.050',
+ '1.05000': '1.050',
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-250.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-250.js
new file mode 100644
index 0000000000..6e13faef71
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-250.js
@@ -0,0 +1,41 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: When set to `250`, roundingIncrement is correctly applied
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 250, maximumFractionDigits: 3, minimumFractionDigits: 3},
+ {
+ '1.2500': '1.250',
+ '1.3125': '1.250',
+ '1.3750': '1.500',
+ '1.4375': '1.500',
+ '1.5000': '1.500',
+ }
+);
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 250, maximumFractionDigits: 4, minimumFractionDigits: 4},
+ {
+ '1.02500': '1.0250',
+ '1.03125': '1.0250',
+ '1.03750': '1.0500',
+ '1.04375': '1.0500',
+ '1.05000': '1.0500',
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2500.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2500.js
new file mode 100644
index 0000000000..b7468787c6
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-2500.js
@@ -0,0 +1,41 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: When set to `2500`, roundingIncrement is correctly applied
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 2500, maximumFractionDigits: 4, minimumFractionDigits: 4},
+ {
+ '1.2500': '1.2500',
+ '1.3125': '1.2500',
+ '1.3750': '1.5000',
+ '1.4375': '1.5000',
+ '1.5000': '1.5000',
+ }
+);
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 2500, maximumFractionDigits: 5, minimumFractionDigits: 5},
+ {
+ '1.02500': '1.02500',
+ '1.03125': '1.02500',
+ '1.03750': '1.05000',
+ '1.04375': '1.05000',
+ '1.05000': '1.05000',
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5.js
new file mode 100644
index 0000000000..09db9be9a6
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5.js
@@ -0,0 +1,41 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: When set to `5`, roundingIncrement is correctly applied
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 5, maximumFractionDigits: 1, minimumFractionDigits: 1},
+ {
+ '1.500': '1.5',
+ '1.625': '1.5',
+ '1.750': '2.0',
+ '1.875': '2.0',
+ '2.000': '2.0',
+ }
+);
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 5, maximumFractionDigits: 2, minimumFractionDigits: 2},
+ {
+ '1.0500': '1.05',
+ '1.0625': '1.05',
+ '1.0750': '1.10',
+ '1.0875': '1.10',
+ '1.1000': '1.10',
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-50.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-50.js
new file mode 100644
index 0000000000..ef51cfc607
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-50.js
@@ -0,0 +1,41 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: When set to `50`, roundingIncrement is correctly applied
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 50, maximumFractionDigits: 2, minimumFractionDigits: 2},
+ {
+ '1.500': '1.50',
+ '1.625': '1.50',
+ '1.750': '2.00',
+ '1.875': '2.00',
+ '2.000': '2.00',
+ }
+);
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 50, maximumFractionDigits: 3, minimumFractionDigits: 3},
+ {
+ '1.0500': '1.050',
+ '1.0625': '1.050',
+ '1.0750': '1.100',
+ '1.0875': '1.100',
+ '1.1000': '1.100',
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-500.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-500.js
new file mode 100644
index 0000000000..45c1e67dfe
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-500.js
@@ -0,0 +1,41 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: When set to `500`, roundingIncrement is correctly applied
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 500, maximumFractionDigits: 3, minimumFractionDigits: 3},
+ {
+ '1.500': '1.500',
+ '1.625': '1.500',
+ '1.750': '2.000',
+ '1.875': '2.000',
+ '2.000': '2.000',
+ }
+);
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 500, maximumFractionDigits: 4, minimumFractionDigits: 4},
+ {
+ '1.0500': '1.0500',
+ '1.0625': '1.0500',
+ '1.0750': '1.1000',
+ '1.0875': '1.1000',
+ '1.1000': '1.1000',
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5000.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5000.js
new file mode 100644
index 0000000000..78eac2c2c2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-increment-5000.js
@@ -0,0 +1,41 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: When set to `5000`, roundingIncrement is correctly applied
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 5000, maximumFractionDigits: 4, minimumFractionDigits: 4},
+ {
+ '1.500': '1.5000',
+ '1.625': '1.5000',
+ '1.750': '2.0000',
+ '1.875': '2.0000',
+ '2.000': '2.0000',
+ }
+);
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {roundingIncrement: 5000, maximumFractionDigits: 5, minimumFractionDigits: 5},
+ {
+ '1.0500': '1.05000',
+ '1.0625': '1.05000',
+ '1.0750': '1.10000',
+ '1.0875': '1.10000',
+ '1.1000': '1.10000',
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-ceil.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-ceil.js
new file mode 100644
index 0000000000..3583f38ece
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-ceil.js
@@ -0,0 +1,34 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ When roundingMode is "ceil", rounding tends toward positive infinity
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingMode: 'ceil', maximumSignificantDigits: 2},
+ {
+ '1.101': '1.2',
+ '1.15': '1.2',
+ '1.1999': '1.2',
+ '1.25': '1.3',
+ '0': '0',
+ '-0': '-0',
+ '-1.101': '-1.1',
+ '-1.15': '-1.1',
+ '-1.1999': '-1.1',
+ '-1.25': '-1.2'
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-expand.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-expand.js
new file mode 100644
index 0000000000..1387f1cd77
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-expand.js
@@ -0,0 +1,34 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ When roundingMode is "expand", rounding tends away from zero
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingMode: 'expand', maximumSignificantDigits: 2},
+ {
+ '1.101': '1.2',
+ '1.15': '1.2',
+ '1.1999': '1.2',
+ '1.25': '1.3',
+ '0': '0',
+ '-0': '-0',
+ '-1.101': '-1.2',
+ '-1.15': '-1.2',
+ '-1.1999': '-1.2',
+ '-1.25': '-1.3'
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-floor.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-floor.js
new file mode 100644
index 0000000000..3e2107e388
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-floor.js
@@ -0,0 +1,34 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ When roundingMode is "floor", rounding tends toward negative infinity
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingMode: 'floor', maximumSignificantDigits: 2},
+ {
+ '1.101': '1.1',
+ '1.15': '1.1',
+ '1.1999': '1.1',
+ '1.25': '1.2',
+ '0': '0',
+ '-0': '-0',
+ '-1.101': '-1.2',
+ '-1.15': '-1.2',
+ '-1.1999': '-1.2',
+ '-1.25': '-1.3'
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-ceil.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-ceil.js
new file mode 100644
index 0000000000..c3da65ab0e
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-ceil.js
@@ -0,0 +1,35 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ When roundingMode is "halfExpand", rounding tends toward the closest value
+ with ties tending toward positive infinity
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingMode: 'halfCeil', maximumSignificantDigits: 2},
+ {
+ '1.101': '1.1',
+ '1.15': '1.2',
+ '1.1999': '1.2',
+ '1.25': '1.3',
+ '0': '0',
+ '-0': '-0',
+ '-1.101': '-1.1',
+ '-1.15': '-1.1',
+ '-1.1999': '-1.2',
+ '-1.25': '-1.2'
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-even.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-even.js
new file mode 100644
index 0000000000..0dd7af1626
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-even.js
@@ -0,0 +1,36 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ When roundingMode is "halfEven", rounding tends toward the closest value
+ with ties tending toward the value with even cardinality
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingMode: 'halfEven', maximumSignificantDigits: 2},
+ {
+ '1.101': '1.1',
+ '1.15': '1.2',
+ '1.1999': '1.2',
+ '1.25': '1.2',
+ '0': '0',
+ '-0': '-0',
+ '-1.101': '-1.1',
+ '-1.15': '-1.2',
+ '-1.1999': '-1.2',
+ '-1.25': '-1.2'
+ }
+);
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-expand.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-expand.js
new file mode 100644
index 0000000000..d08b6bac84
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-expand.js
@@ -0,0 +1,35 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ When roundingMode is "halfExpand", rounding tends toward the closest value
+ with ties tending away from zero
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingMode: 'halfExpand', maximumSignificantDigits: 2},
+ {
+ '1.101': '1.1',
+ '1.15': '1.2',
+ '1.1999': '1.2',
+ '1.25': '1.3',
+ '0': '0',
+ '-0': '-0',
+ '-1.101': '-1.1',
+ '-1.15': '-1.2',
+ '-1.1999': '-1.2',
+ '-1.25': '-1.3'
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-floor.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-floor.js
new file mode 100644
index 0000000000..42a5ce98d2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-floor.js
@@ -0,0 +1,35 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ When roundingMode is "halfFloor", rounding tends toward the closest value
+ with ties tending toward negative infinity
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingMode: 'halfFloor', maximumSignificantDigits: 2},
+ {
+ '1.101': '1.1',
+ '1.15': '1.1',
+ '1.1999': '1.2',
+ '1.25': '1.2',
+ '0': '0',
+ '-0': '-0',
+ '-1.101': '-1.1',
+ '-1.15': '-1.2',
+ '-1.1999': '-1.2',
+ '-1.25': '-1.3'
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-trunc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-trunc.js
new file mode 100644
index 0000000000..b6babdb903
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-half-trunc.js
@@ -0,0 +1,35 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ When roundingMode is "halfTrunc", rounding tends toward the closest value
+ with ties tending toward zero
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingMode: 'halfTrunc', maximumSignificantDigits: 2},
+ {
+ '1.101': '1.1',
+ '1.15': '1.1',
+ '1.1999': '1.2',
+ '1.25': '1.2',
+ '0': '0',
+ '-0': '-0',
+ '-1.101': '-1.1',
+ '-1.15': '-1.1',
+ '-1.1999': '-1.2',
+ '-1.25': '-1.2'
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-trunc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-trunc.js
new file mode 100644
index 0000000000..8c8444ef9c
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-mode-trunc.js
@@ -0,0 +1,34 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ When roundingMode is "trunc", rounding tends toward zero
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingMode: 'trunc', maximumSignificantDigits: 2},
+ {
+ '1.101': '1.1',
+ '1.15': '1.1',
+ '1.1999': '1.1',
+ '1.25': '1.2',
+ '0': '0',
+ '-0': '-0',
+ '-1.101': '-1.1',
+ '-1.15': '-1.1',
+ '-1.1999': '-1.1',
+ '-1.25': '-1.2'
+ }
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-auto.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-auto.js
new file mode 100644
index 0000000000..2199dd6b53
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-auto.js
@@ -0,0 +1,49 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ When roungingPriority is "auto", the constraint on significant digits is
+ preferred over the constraint on fraction digits
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+// minimumSignificantDigits is less precise
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingPriority: 'auto', minimumSignificantDigits: 2, minimumFractionDigitsDigits: 2},
+ {'1': '1.0'}
+);
+
+// minimumSignificantDigits is more precise
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingPriority: 'auto', minimumSignificantDigits: 3, minimumFractionDigitsDigits: 2},
+ {'1': '1.00'}
+);
+
+// maximumSignificantDigits is less precise
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingPriority: 'auto', maximumSignificantDigits: 2, maximumFractionDigitsDigits: 2},
+ {'1.23': '1.2'}
+);
+
+// maximumSignificantDigits is more precise
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingPriority: 'auto', maximumSignificantDigits: 3, maximumFractionDigitsDigits: 1},
+ {'1.234': '1.23'}
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-less-precision.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-less-precision.js
new file mode 100644
index 0000000000..2a50ef5cc0
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-less-precision.js
@@ -0,0 +1,49 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ When roungingPriority is "lessPrecision", the constraint which produces the
+ less precise result is preferred
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+// minimumSignificantDigits is less precise
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingPriority: 'lessPrecision', minimumSignificantDigits: 2, minimumFractionDigits: 2},
+ {'1': '1.00'}
+);
+
+// minimumSignificantDigits is more precise
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingPriority: 'lessPrecision', minimumSignificantDigits: 3, minimumFractionDigits: 1},
+ {'1': '1.0'}
+);
+
+// maximumSignificantDigits is less precise
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingPriority: 'lessPrecision', maximumSignificantDigits: 2, maximumFractionDigits: 2},
+ {'1.23': '1.2'}
+);
+
+// maximumSignificantDigits is more precise
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingPriority: 'lessPrecision', maximumSignificantDigits: 3, maximumFractionDigits: 1},
+ {'1.234': '1.2'}
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-more-precision.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-more-precision.js
new file mode 100644
index 0000000000..dbe4b3a8a5
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-rounding-priority-more-precision.js
@@ -0,0 +1,49 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ When roungingPriority is "morePrecision", the constraint which produces the
+ more precise result is preferred
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'
+];
+var numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+// maximumSignificantDigits defaults to 21, beating maximumFractionDigits, which defaults to 3
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingPriority: 'morePrecision', minimumSignificantDigits: 2, minimumFractionDigits: 2},
+ {'1': '1.0'}
+);
+
+// maximumSignificantDigits defaults to 21, beating maximumFractionDigits, which defaults to 3
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingPriority: 'morePrecision', minimumSignificantDigits: 3, minimumFractionDigits: 2},
+ {'1': '1.00'}
+);
+
+// maximumSignificantDigits is less precise
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingPriority: 'morePrecision', maximumSignificantDigits: 2, maximumFractionDigits: 2},
+ {'1.23': '1.23'}
+);
+
+// maximumSignificantDigits is more precise
+testNumberFormat(
+ locales,
+ numberingSystems,
+ {useGrouping: false, roundingPriority: 'morePrecision', maximumSignificantDigits: 3, maximumFractionDigits: 1},
+ {'1.234': '1.23'}
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-significant-digits-precision.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-significant-digits-precision.js
new file mode 100644
index 0000000000..dfb0aa7f59
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-significant-digits-precision.js
@@ -0,0 +1,34 @@
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.3.2_TRP
+description: >
+ Tests that the digits are determined correctly when specifying
+ significant digits.
+author: Norbert Lindenberg
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale,
+ "ar", "de", "th", "ja"
+];
+var numberingSystems = [
+ "arab",
+ "latn",
+ "thai",
+ "hanidec"
+];
+var testData = {
+ // Ref tc39/ecma402#128
+ "123.44500": "123.45",
+ "-123.44500": "-123.45",
+};
+
+testNumberFormat(locales, numberingSystems,
+ {useGrouping: false, minimumSignificantDigits: 3, maximumSignificantDigits: 5},
+ testData);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-significant-digits.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-significant-digits.js
new file mode 100644
index 0000000000..d9cc063af5
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-significant-digits.js
@@ -0,0 +1,57 @@
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.3.2_TRP
+description: >
+ Tests that the digits are determined correctly when specifying
+ significant digits.
+author: Norbert Lindenberg
+includes: [testIntl.js]
+---*/
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale,
+ "ar", "de", "th", "ja"
+];
+var numberingSystems = [
+ "arab",
+ "latn",
+ "thai",
+ "hanidec"
+];
+var testData = {
+ "0": "0.00",
+ "-0": "-0.00",
+ "123": "123",
+ "-123": "-123",
+ "12345": "12345",
+ "-12345": "-12345",
+ "123.45": "123.45",
+ "-123.45": "-123.45",
+ "123.44499": "123.44",
+ "-123.44499": "-123.44",
+ "123.44501": "123.45",
+ "-123.44501": "-123.45",
+ "0.001234": "0.001234",
+ "-0.001234": "-0.001234",
+ "0.00000000123": "0.00000000123",
+ "-0.00000000123": "-0.00000000123",
+ "0.00000000000000000000000000000123": "0.00000000000000000000000000000123",
+ "-0.00000000000000000000000000000123": "-0.00000000000000000000000000000123",
+ "1.2": "1.20",
+ "-1.2": "-1.20",
+ "0.0000000012344501": "0.0000000012345",
+ "-0.0000000012344501": "-0.0000000012345",
+ "123445.01": "123450",
+ "-123445.01": "-123450",
+ "12344501000000000000000000000000000": "12345000000000000000000000000000000",
+ "-12344501000000000000000000000000000": "-12345000000000000000000000000000000"
+};
+
+testNumberFormat(locales, numberingSystems,
+ {useGrouping: false, minimumSignificantDigits: 3, maximumSignificantDigits: 5},
+ testData);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/length.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/length.js
new file mode 100644
index 0000000000..c49e212b7f
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/length.js
@@ -0,0 +1,36 @@
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ get Intl.NumberFormat.prototype.format.length is 0.
+info: |
+ get Intl.NumberFormat.prototype.format
+
+ 17 ECMAScript Standard Built-in Objects:
+
+ Every built-in function object, including constructors, has a length
+ property whose value is an integer. Unless otherwise specified, this
+ value is equal to the largest number of named arguments shown in the
+ subclause headings for the function description. Optional parameters
+ (which are indicated with brackets: [ ]) or rest parameters (which
+ are shown using the form «...name») are not included in the default
+ argument count.
+ Unless otherwise specified, the length property of a built-in function
+ object has the attributes { [[Writable]]: false, [[Enumerable]]: false,
+ [[Configurable]]: true }.
+
+includes: [propertyHelper.js]
+---*/
+
+var desc = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format");
+
+verifyProperty(desc.get, "length", {
+ value: 0,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/name.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/name.js
new file mode 100644
index 0000000000..48416d7aa6
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/name.js
@@ -0,0 +1,31 @@
+// Copyright (C) 2016 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat.prototype.format
+description: >
+ get Intl.NumberFormat.prototype.format.name is "get format".
+info: |
+ 11.4.3 get Intl.NumberFormat.prototype.format
+
+ 17 ECMAScript Standard Built-in Objects:
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value
+ is a String.
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+includes: [propertyHelper.js]
+---*/
+
+var desc = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format");
+
+verifyProperty(desc.get, "name", {
+ value: "get format",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/no-instanceof.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/no-instanceof.js
new file mode 100644
index 0000000000..03a4f7eac2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/no-instanceof.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 Igalia S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ Tests that Intl.NumberFormat.prototype.format calls
+ OrdinaryHasInstance instead of the instanceof operator which includes a
+ Symbol.hasInstance lookup and call among other things.
+info: >
+ UnwrapNumberFormat ( nf )
+
+ 2. If nf does not have an [[InitializedNumberFormat]] internal slot and
+ ? OrdinaryHasInstance(%NumberFormat%, nf) is true, then
+ a. Return ? Get(nf, %Intl%.[[FallbackSymbol]]).
+---*/
+
+const nf = Object.create(Intl.NumberFormat.prototype);
+
+Object.defineProperty(Intl.NumberFormat, Symbol.hasInstance, {
+ get() { throw new Test262Error(); }
+});
+
+assert.throws(TypeError, () => nf.format);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-de-DE.js
new file mode 100644
index 0000000000..bd33e60f6a
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-de-DE.js
@@ -0,0 +1,47 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the compactDisplay option to the NumberFormat constructor.
+locale: [de-DE]
+features: [Intl.NumberFormat-unified]
+---*/
+
+const nfShort = new Intl.NumberFormat("de-DE", {
+ notation: "compact",
+ compactDisplay: "short",
+});
+assert.sameValue(nfShort.format(987654321), "988\u00a0Mio.");
+assert.sameValue(nfShort.format(98765432), "99\u00a0Mio.");
+assert.sameValue(nfShort.format(98765), "98.765");
+assert.sameValue(nfShort.format(9876), "9876");
+assert.sameValue(nfShort.format(159), "159");
+assert.sameValue(nfShort.format(15.9), "16");
+assert.sameValue(nfShort.format(1.59), "1,6");
+assert.sameValue(nfShort.format(0.159), "0,16");
+assert.sameValue(nfShort.format(0.0159), "0,016");
+assert.sameValue(nfShort.format(0.00159), "0,0016");
+assert.sameValue(nfShort.format(-Infinity), "-∞");
+assert.sameValue(nfShort.format(Infinity), "∞");
+assert.sameValue(nfShort.format(NaN), "NaN");
+
+const nfLong = new Intl.NumberFormat("de-DE", {
+ notation: "compact",
+ compactDisplay: "long",
+});
+assert.sameValue(nfLong.format(987654321), "988 Millionen");
+assert.sameValue(nfLong.format(98765432), "99 Millionen");
+assert.sameValue(nfLong.format(98765), "99 Tausend");
+assert.sameValue(nfLong.format(9876), "9,9 Tausend");
+assert.sameValue(nfLong.format(159), "159");
+assert.sameValue(nfLong.format(15.9), "16");
+assert.sameValue(nfLong.format(1.59), "1,6");
+assert.sameValue(nfLong.format(0.159), "0,16");
+assert.sameValue(nfLong.format(0.0159), "0,016");
+assert.sameValue(nfLong.format(0.00159), "0,0016");
+assert.sameValue(nfLong.format(-Infinity), "-∞");
+assert.sameValue(nfLong.format(Infinity), "∞");
+assert.sameValue(nfLong.format(NaN), "NaN");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-en-US.js
new file mode 100644
index 0000000000..09856d66c3
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-en-US.js
@@ -0,0 +1,47 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the compactDisplay option to the NumberFormat constructor.
+locale: [en-US]
+features: [Intl.NumberFormat-unified]
+---*/
+
+const nfShort = new Intl.NumberFormat("en-US", {
+ notation: "compact",
+ compactDisplay: "short",
+});
+assert.sameValue(nfShort.format(987654321), "988M");
+assert.sameValue(nfShort.format(98765432), "99M");
+assert.sameValue(nfShort.format(98765), "99K");
+assert.sameValue(nfShort.format(9876), "9.9K");
+assert.sameValue(nfShort.format(159), "159");
+assert.sameValue(nfShort.format(15.9), "16");
+assert.sameValue(nfShort.format(1.59), "1.6");
+assert.sameValue(nfShort.format(0.159), "0.16");
+assert.sameValue(nfShort.format(0.0159), "0.016");
+assert.sameValue(nfShort.format(0.00159), "0.0016");
+assert.sameValue(nfShort.format(-Infinity), "-∞");
+assert.sameValue(nfShort.format(Infinity), "∞");
+assert.sameValue(nfShort.format(NaN), "NaN");
+
+const nfLong = new Intl.NumberFormat("en-US", {
+ notation: "compact",
+ compactDisplay: "long",
+});
+assert.sameValue(nfLong.format(987654321), "988 million");
+assert.sameValue(nfLong.format(98765432), "99 million");
+assert.sameValue(nfLong.format(98765), "99 thousand");
+assert.sameValue(nfLong.format(9876), "9.9 thousand");
+assert.sameValue(nfLong.format(159), "159");
+assert.sameValue(nfLong.format(15.9), "16");
+assert.sameValue(nfLong.format(1.59), "1.6");
+assert.sameValue(nfLong.format(0.159), "0.16");
+assert.sameValue(nfLong.format(0.0159), "0.016");
+assert.sameValue(nfLong.format(0.00159), "0.0016");
+assert.sameValue(nfLong.format(-Infinity), "-∞");
+assert.sameValue(nfLong.format(Infinity), "∞");
+assert.sameValue(nfLong.format(NaN), "NaN");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-ja-JP.js
new file mode 100644
index 0000000000..24e6dbfd4f
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-ja-JP.js
@@ -0,0 +1,47 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the compactDisplay option to the NumberFormat constructor.
+locale: [ja-JP]
+features: [Intl.NumberFormat-unified]
+---*/
+
+const nfShort = new Intl.NumberFormat("ja-JP", {
+ notation: "compact",
+ compactDisplay: "short",
+});
+assert.sameValue(nfShort.format(987654321), "9.9億");
+assert.sameValue(nfShort.format(98765432), "9877万");
+assert.sameValue(nfShort.format(98765), "9.9万");
+assert.sameValue(nfShort.format(9876), "9876");
+assert.sameValue(nfShort.format(159), "159");
+assert.sameValue(nfShort.format(15.9), "16");
+assert.sameValue(nfShort.format(1.59), "1.6");
+assert.sameValue(nfShort.format(0.159), "0.16");
+assert.sameValue(nfShort.format(0.0159), "0.016");
+assert.sameValue(nfShort.format(0.00159), "0.0016");
+assert.sameValue(nfShort.format(-Infinity), "-∞");
+assert.sameValue(nfShort.format(Infinity), "∞");
+assert.sameValue(nfShort.format(NaN), "NaN");
+
+const nfLong = new Intl.NumberFormat("ja-JP", {
+ notation: "compact",
+ compactDisplay: "long",
+});
+assert.sameValue(nfLong.format(987654321), "9.9億");
+assert.sameValue(nfLong.format(98765432), "9877万");
+assert.sameValue(nfLong.format(98765), "9.9万");
+assert.sameValue(nfLong.format(9876), "9876");
+assert.sameValue(nfLong.format(159), "159");
+assert.sameValue(nfLong.format(15.9), "16");
+assert.sameValue(nfLong.format(1.59), "1.6");
+assert.sameValue(nfLong.format(0.159), "0.16");
+assert.sameValue(nfLong.format(0.0159), "0.016");
+assert.sameValue(nfLong.format(0.00159), "0.0016");
+assert.sameValue(nfLong.format(-Infinity), "-∞");
+assert.sameValue(nfLong.format(Infinity), "∞");
+assert.sameValue(nfLong.format(NaN), "NaN");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-ko-KR.js
new file mode 100644
index 0000000000..d24f3a6e20
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-ko-KR.js
@@ -0,0 +1,47 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the compactDisplay option to the NumberFormat constructor.
+locale: [ko-KR]
+features: [Intl.NumberFormat-unified]
+---*/
+
+const nfShort = new Intl.NumberFormat("ko-KR", {
+ notation: "compact",
+ compactDisplay: "short",
+});
+assert.sameValue(nfShort.format(987654321), "9.9억");
+assert.sameValue(nfShort.format(98765432), "9877만");
+assert.sameValue(nfShort.format(98765), "9.9만");
+assert.sameValue(nfShort.format(9876), "9.9천");
+assert.sameValue(nfShort.format(159), "159");
+assert.sameValue(nfShort.format(15.9), "16");
+assert.sameValue(nfShort.format(1.59), "1.6");
+assert.sameValue(nfShort.format(0.159), "0.16");
+assert.sameValue(nfShort.format(0.0159), "0.016");
+assert.sameValue(nfShort.format(0.00159), "0.0016");
+assert.sameValue(nfShort.format(-Infinity), "-∞");
+assert.sameValue(nfShort.format(Infinity), "∞");
+assert.sameValue(nfShort.format(NaN), "NaN");
+
+const nfLong = new Intl.NumberFormat("ko-KR", {
+ notation: "compact",
+ compactDisplay: "long",
+});
+assert.sameValue(nfLong.format(987654321), "9.9억");
+assert.sameValue(nfLong.format(98765432), "9877만");
+assert.sameValue(nfLong.format(98765), "9.9만");
+assert.sameValue(nfLong.format(9876), "9.9천");
+assert.sameValue(nfLong.format(159), "159");
+assert.sameValue(nfLong.format(15.9), "16");
+assert.sameValue(nfLong.format(1.59), "1.6");
+assert.sameValue(nfLong.format(0.159), "0.16");
+assert.sameValue(nfLong.format(0.0159), "0.016");
+assert.sameValue(nfLong.format(0.00159), "0.0016");
+assert.sameValue(nfLong.format(-Infinity), "-∞");
+assert.sameValue(nfLong.format(Infinity), "∞");
+assert.sameValue(nfLong.format(NaN), "NaN");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-zh-TW.js
new file mode 100644
index 0000000000..92e33a7922
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-zh-TW.js
@@ -0,0 +1,47 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the compactDisplay option to the NumberFormat constructor.
+locale: [zh-TW]
+features: [Intl.NumberFormat-unified]
+---*/
+
+const nfShort = new Intl.NumberFormat("zh-TW", {
+ notation: "compact",
+ compactDisplay: "short",
+});
+assert.sameValue(nfShort.format(987654321), "9.9億");
+assert.sameValue(nfShort.format(98765432), "9877萬");
+assert.sameValue(nfShort.format(98765), "9.9萬");
+assert.sameValue(nfShort.format(9876), "9876");
+assert.sameValue(nfShort.format(159), "159");
+assert.sameValue(nfShort.format(15.9), "16");
+assert.sameValue(nfShort.format(1.59), "1.6");
+assert.sameValue(nfShort.format(0.159), "0.16");
+assert.sameValue(nfShort.format(0.0159), "0.016");
+assert.sameValue(nfShort.format(0.00159), "0.0016");
+assert.sameValue(nfShort.format(-Infinity), "-∞");
+assert.sameValue(nfShort.format(Infinity), "∞");
+assert.sameValue(nfShort.format(NaN), "非數值");
+
+const nfLong = new Intl.NumberFormat("zh-TW", {
+ notation: "compact",
+ compactDisplay: "long",
+});
+assert.sameValue(nfLong.format(987654321), "9.9億");
+assert.sameValue(nfLong.format(98765432), "9877萬");
+assert.sameValue(nfLong.format(98765), "9.9萬");
+assert.sameValue(nfLong.format(9876), "9876");
+assert.sameValue(nfLong.format(159), "159");
+assert.sameValue(nfLong.format(15.9), "16");
+assert.sameValue(nfLong.format(1.59), "1.6");
+assert.sameValue(nfLong.format(0.159), "0.16");
+assert.sameValue(nfLong.format(0.0159), "0.016");
+assert.sameValue(nfLong.format(0.00159), "0.0016");
+assert.sameValue(nfLong.format(-Infinity), "-∞");
+assert.sameValue(nfLong.format(Infinity), "∞");
+assert.sameValue(nfLong.format(NaN), "非數值");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/numbering-systems.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/numbering-systems.js
new file mode 100644
index 0000000000..112657283c
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/numbering-systems.js
@@ -0,0 +1,25 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: table-numbering-system-digits
+description: >
+ Tests that Intl.NumberFormat.prototype.format supports all
+ numbering systems with simple digit mappings.
+author: Roozbeh Pournader
+includes: [testIntl.js]
+---*/
+
+for (let [numberingSystem, digits] of Object.entries(numberingSystemDigits)) {
+ let digitList = [...digits];
+ assert.sameValue(digitList.length, 10);
+
+ let nf = new Intl.NumberFormat(undefined, {numberingSystem});
+
+ for (let i = 0; i <= 9; ++i) {
+ assert.sameValue(nf.format(i), digitList[i],
+ `numberingSystem: ${numberingSystem}, digit: ${i}`);
+ }
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/percent-formatter.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/percent-formatter.js
new file mode 100644
index 0000000000..5dc7f70e9e
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/percent-formatter.js
@@ -0,0 +1,25 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.3.2_FN_3_b
+description: >
+ Tests that Intl.NumberFormat.prototype.format formats percent
+ values properly.
+author: Roozbeh Pournader
+---*/
+
+var numberFormatter = new Intl.NumberFormat();
+var percentFormatter = new Intl.NumberFormat(undefined, {style: 'percent'});
+
+var formattedTwenty = numberFormatter.format(20);
+var formattedTwentyPercent = percentFormatter.format(0.20);
+
+// FIXME: May not work for some theoretical locales where percents and
+// normal numbers are formatted using different numbering systems.
+assert.notSameValue(formattedTwentyPercent.indexOf(formattedTwenty), -1, "Intl.NumberFormat's formatting of 20% does not include a formatting of 20 as a substring.");
+
+// FIXME: Move this to somewhere appropriate
+assert.notSameValue(percentFormatter.format(0.011), percentFormatter.format(0.02), 'Intl.NumberFormat is formatting 1.1% and 2% the same way.');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/prop-desc.js
new file mode 100644
index 0000000000..5a2847722d
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/prop-desc.js
@@ -0,0 +1,39 @@
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ "format" property of Intl.NumberFormat.prototype.
+info: |
+ get Intl.NumberFormat.prototype.format
+
+ 7 Requirements for Standard Built-in ECMAScript Objects
+
+ Unless specified otherwise in this document, the objects, functions, and constructors
+ described in this standard are subject to the generic requirements and restrictions
+ specified for standard built-in ECMAScript objects in the ECMAScript 2018 Language
+ Specification, 9th edition, clause 17, or successor.
+
+ 17 ECMAScript Standard Built-in Objects:
+
+ Every accessor property described in clauses 18 through 26 and in Annex B.2 has the
+ attributes { [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified.
+ If only a get accessor function is described, the set accessor function is the default
+ value, undefined. If only a set accessor is described the get accessor is the default
+ value, undefined.
+
+includes: [propertyHelper.js]
+---*/
+
+var desc = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format");
+
+assert.sameValue(desc.set, undefined);
+assert.sameValue(typeof desc.get, "function");
+
+verifyProperty(Intl.NumberFormat.prototype, "format", {
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/shell.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/shell.js
@@ -0,0 +1,24 @@
+// GENERATED, DO NOT EDIT
+// file: isConstructor.js
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: |
+ Test if a given function is a constructor function.
+defines: [isConstructor]
+features: [Reflect.construct]
+---*/
+
+function isConstructor(f) {
+ if (typeof f !== "function") {
+ throw new Test262Error("isConstructor invoked with a non-function value");
+ }
+
+ try {
+ Reflect.construct(function(){}, [], f);
+ } catch (e) {
+ return false;
+ }
+ return true;
+}
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-de-DE.js
new file mode 100644
index 0000000000..72d8ccc410
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-de-DE.js
@@ -0,0 +1,62 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [de-DE]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ "auto",
+ "-987,00 $",
+ "-0,00 $",
+ "-0,00 $",
+ "0,00 $",
+ "0,00 $",
+ "987,00 $",
+ ],
+ [
+ "always",
+ "-987,00 $",
+ "-0,00 $",
+ "-0,00 $",
+ "+0,00 $",
+ "+0,00 $",
+ "+987,00 $",
+ ],
+ [
+ "never",
+ "987,00 $",
+ "0,00 $",
+ "0,00 $",
+ "0,00 $",
+ "0,00 $",
+ "987,00 $",
+ ],
+ [
+ "exceptZero",
+ "-987,00 $",
+ "0,00 $",
+ "0,00 $",
+ "0,00 $",
+ "0,00 $",
+ "+987,00 $",
+ ],
+];
+
+for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) {
+ const nf = new Intl.NumberFormat("de-DE", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay });
+ assert.sameValue(nf.format(-987), negative);
+ assert.sameValue(nf.format(-0.0001), negativeNearZero);
+ assert.sameValue(nf.format(-0), negativeZero);
+ assert.sameValue(nf.format(0), zero);
+ assert.sameValue(nf.format(0.0001), positiveNearZero);
+ assert.sameValue(nf.format(987), positive);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-en-US.js
new file mode 100644
index 0000000000..72a1a0ba2e
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-en-US.js
@@ -0,0 +1,62 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [en-US]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ "auto",
+ "($987.00)",
+ "($0.00)",
+ "($0.00)",
+ "$0.00",
+ "$0.00",
+ "$987.00",
+ ],
+ [
+ "always",
+ "($987.00)",
+ "($0.00)",
+ "($0.00)",
+ "+$0.00",
+ "+$0.00",
+ "+$987.00",
+ ],
+ [
+ "never",
+ "$987.00",
+ "$0.00",
+ "$0.00",
+ "$0.00",
+ "$0.00",
+ "$987.00",
+ ],
+ [
+ "exceptZero",
+ "($987.00)",
+ "$0.00",
+ "$0.00",
+ "$0.00",
+ "$0.00",
+ "+$987.00",
+ ],
+];
+
+for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) {
+ const nf = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay });
+ assert.sameValue(nf.format(-987), negative);
+ assert.sameValue(nf.format(-0.0001), negativeNearZero);
+ assert.sameValue(nf.format(-0), negativeZero);
+ assert.sameValue(nf.format(0), zero);
+ assert.sameValue(nf.format(0.0001), positiveNearZero);
+ assert.sameValue(nf.format(987), positive);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ja-JP.js
new file mode 100644
index 0000000000..f28ba6c263
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ja-JP.js
@@ -0,0 +1,62 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [ja-JP]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ "auto",
+ "($987.00)",
+ "($0.00)",
+ "($0.00)",
+ "$0.00",
+ "$0.00",
+ "$987.00",
+ ],
+ [
+ "always",
+ "($987.00)",
+ "($0.00)",
+ "($0.00)",
+ "+$0.00",
+ "+$0.00",
+ "+$987.00",
+ ],
+ [
+ "never",
+ "$987.00",
+ "$0.00",
+ "$0.00",
+ "$0.00",
+ "$0.00",
+ "$987.00",
+ ],
+ [
+ "exceptZero",
+ "($987.00)",
+ "$0.00",
+ "$0.00",
+ "$0.00",
+ "$0.00",
+ "+$987.00",
+ ],
+];
+
+for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) {
+ const nf = new Intl.NumberFormat("ja-JP", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay });
+ assert.sameValue(nf.format(-987), negative);
+ assert.sameValue(nf.format(-0.0001), negativeNearZero);
+ assert.sameValue(nf.format(-0), negativeZero);
+ assert.sameValue(nf.format(0), zero);
+ assert.sameValue(nf.format(0.0001), positiveNearZero);
+ assert.sameValue(nf.format(987), positive);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ko-KR.js
new file mode 100644
index 0000000000..cfe8f9393a
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ko-KR.js
@@ -0,0 +1,62 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [ko-KR]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ "auto",
+ "(US$987.00)",
+ "(US$0.00)",
+ "(US$0.00)",
+ "US$0.00",
+ "US$0.00",
+ "US$987.00",
+ ],
+ [
+ "always",
+ "(US$987.00)",
+ "(US$0.00)",
+ "(US$0.00)",
+ "+US$0.00",
+ "+US$0.00",
+ "+US$987.00",
+ ],
+ [
+ "never",
+ "US$987.00",
+ "US$0.00",
+ "US$0.00",
+ "US$0.00",
+ "US$0.00",
+ "US$987.00",
+ ],
+ [
+ "exceptZero",
+ "(US$987.00)",
+ "US$0.00",
+ "US$0.00",
+ "US$0.00",
+ "US$0.00",
+ "+US$987.00",
+ ],
+];
+
+for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) {
+ const nf = new Intl.NumberFormat("ko-KR", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay });
+ assert.sameValue(nf.format(-987), negative);
+ assert.sameValue(nf.format(-0.0001), negativeNearZero);
+ assert.sameValue(nf.format(-0), negativeZero);
+ assert.sameValue(nf.format(0), zero);
+ assert.sameValue(nf.format(0.0001), positiveNearZero);
+ assert.sameValue(nf.format(987), positive);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-zh-TW.js
new file mode 100644
index 0000000000..677b0b400e
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-zh-TW.js
@@ -0,0 +1,62 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [zh-TW]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ "auto",
+ "(US$987.00)",
+ "(US$0.00)",
+ "(US$0.00)",
+ "US$0.00",
+ "US$0.00",
+ "US$987.00",
+ ],
+ [
+ "always",
+ "(US$987.00)",
+ "(US$0.00)",
+ "(US$0.00)",
+ "+US$0.00",
+ "+US$0.00",
+ "+US$987.00",
+ ],
+ [
+ "never",
+ "US$987.00",
+ "US$0.00",
+ "US$0.00",
+ "US$0.00",
+ "US$0.00",
+ "US$987.00",
+ ],
+ [
+ "exceptZero",
+ "(US$987.00)",
+ "US$0.00",
+ "US$0.00",
+ "US$0.00",
+ "US$0.00",
+ "+US$987.00",
+ ],
+];
+
+for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) {
+ const nf = new Intl.NumberFormat("zh-TW", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay });
+ assert.sameValue(nf.format(-987), negative);
+ assert.sameValue(nf.format(-0.0001), negativeNearZero);
+ assert.sameValue(nf.format(-0), negativeZero);
+ assert.sameValue(nf.format(0), zero);
+ assert.sameValue(nf.format(0.0001), positiveNearZero);
+ assert.sameValue(nf.format(987), positive);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-de-DE.js
new file mode 100644
index 0000000000..8d7a04d7cd
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-de-DE.js
@@ -0,0 +1,77 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [de-DE]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ "auto",
+ "-∞",
+ "-987",
+ "-0",
+ "-0",
+ "0",
+ "0",
+ "987",
+ "∞",
+ "NaN",
+ ],
+ [
+ "always",
+ "-∞",
+ "-987",
+ "-0",
+ "-0",
+ "+0",
+ "+0",
+ "+987",
+ "+∞",
+ "+NaN",
+ ],
+ [
+ "never",
+ "∞",
+ "987",
+ "0",
+ "0",
+ "0",
+ "0",
+ "987",
+ "∞",
+ "NaN",
+ ],
+ [
+ "exceptZero",
+ "-∞",
+ "-987",
+ "0",
+ "0",
+ "0",
+ "0",
+ "+987",
+ "+∞",
+ "NaN",
+ ],
+];
+
+for (const [signDisplay, ...expected] of tests) {
+ const nf = new Intl.NumberFormat("de-DE", {signDisplay});
+ assert.sameValue(nf.format(-Infinity), expected[0], `-Infinity (${signDisplay})`);
+ assert.sameValue(nf.format(-987), expected[1], `-987 (${signDisplay})`);
+ assert.sameValue(nf.format(-0.0001), expected[2], `-0.0001 (${signDisplay})`);
+ assert.sameValue(nf.format(-0), expected[3], `-0 (${signDisplay})`);
+ assert.sameValue(nf.format(0), expected[4], `0 (${signDisplay})`);
+ assert.sameValue(nf.format(0.0001), expected[5], `0.0001 (${signDisplay})`);
+ assert.sameValue(nf.format(987), expected[6], `987 (${signDisplay})`);
+ assert.sameValue(nf.format(Infinity), expected[7], `Infinity (${signDisplay})`);
+ assert.sameValue(nf.format(NaN), expected[8], `NaN (${signDisplay})`);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-en-US.js
new file mode 100644
index 0000000000..7b756562e6
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-en-US.js
@@ -0,0 +1,77 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [en-US]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ "auto",
+ "-∞",
+ "-987",
+ "-0",
+ "-0",
+ "0",
+ "0",
+ "987",
+ "∞",
+ "NaN",
+ ],
+ [
+ "always",
+ "-∞",
+ "-987",
+ "-0",
+ "-0",
+ "+0",
+ "+0",
+ "+987",
+ "+∞",
+ "+NaN",
+ ],
+ [
+ "never",
+ "∞",
+ "987",
+ "0",
+ "0",
+ "0",
+ "0",
+ "987",
+ "∞",
+ "NaN",
+ ],
+ [
+ "exceptZero",
+ "-∞",
+ "-987",
+ "0",
+ "0",
+ "0",
+ "0",
+ "+987",
+ "+∞",
+ "NaN",
+ ],
+];
+
+for (const [signDisplay, ...expected] of tests) {
+ const nf = new Intl.NumberFormat("en-US", {signDisplay});
+ assert.sameValue(nf.format(-Infinity), expected[0], `-Infinity (${signDisplay})`);
+ assert.sameValue(nf.format(-987), expected[1], `-987 (${signDisplay})`);
+ assert.sameValue(nf.format(-0.0001), expected[2], `-0.0001 (${signDisplay})`);
+ assert.sameValue(nf.format(-0), expected[3], `-0 (${signDisplay})`);
+ assert.sameValue(nf.format(0), expected[4], `0 (${signDisplay})`);
+ assert.sameValue(nf.format(0.0001), expected[5], `0.0001 (${signDisplay})`);
+ assert.sameValue(nf.format(987), expected[6], `987 (${signDisplay})`);
+ assert.sameValue(nf.format(Infinity), expected[7], `Infinity (${signDisplay})`);
+ assert.sameValue(nf.format(NaN), expected[8], `NaN (${signDisplay})`);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-ja-JP.js
new file mode 100644
index 0000000000..8074c621bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-ja-JP.js
@@ -0,0 +1,77 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [ja-JP]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ "auto",
+ "-∞",
+ "-987",
+ "-0",
+ "-0",
+ "0",
+ "0",
+ "987",
+ "∞",
+ "NaN",
+ ],
+ [
+ "always",
+ "-∞",
+ "-987",
+ "-0",
+ "-0",
+ "+0",
+ "+0",
+ "+987",
+ "+∞",
+ "+NaN",
+ ],
+ [
+ "never",
+ "∞",
+ "987",
+ "0",
+ "0",
+ "0",
+ "0",
+ "987",
+ "∞",
+ "NaN",
+ ],
+ [
+ "exceptZero",
+ "-∞",
+ "-987",
+ "0",
+ "0",
+ "0",
+ "0",
+ "+987",
+ "+∞",
+ "NaN",
+ ],
+];
+
+for (const [signDisplay, ...expected] of tests) {
+ const nf = new Intl.NumberFormat("ja-JP", {signDisplay});
+ assert.sameValue(nf.format(-Infinity), expected[0], `-Infinity (${signDisplay})`);
+ assert.sameValue(nf.format(-987), expected[1], `-987 (${signDisplay})`);
+ assert.sameValue(nf.format(-0.0001), expected[2], `-0.0001 (${signDisplay})`);
+ assert.sameValue(nf.format(-0), expected[3], `-0 (${signDisplay})`);
+ assert.sameValue(nf.format(0), expected[4], `0 (${signDisplay})`);
+ assert.sameValue(nf.format(0.0001), expected[5], `0.0001 (${signDisplay})`);
+ assert.sameValue(nf.format(987), expected[6], `987 (${signDisplay})`);
+ assert.sameValue(nf.format(Infinity), expected[7], `Infinity (${signDisplay})`);
+ assert.sameValue(nf.format(NaN), expected[8], `NaN (${signDisplay})`);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-ko-KR.js
new file mode 100644
index 0000000000..45029e8f89
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-ko-KR.js
@@ -0,0 +1,77 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [ko-KR]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ "auto",
+ "-∞",
+ "-987",
+ "-0",
+ "-0",
+ "0",
+ "0",
+ "987",
+ "∞",
+ "NaN",
+ ],
+ [
+ "always",
+ "-∞",
+ "-987",
+ "-0",
+ "-0",
+ "+0",
+ "+0",
+ "+987",
+ "+∞",
+ "+NaN",
+ ],
+ [
+ "never",
+ "∞",
+ "987",
+ "0",
+ "0",
+ "0",
+ "0",
+ "987",
+ "∞",
+ "NaN",
+ ],
+ [
+ "exceptZero",
+ "-∞",
+ "-987",
+ "0",
+ "0",
+ "0",
+ "0",
+ "+987",
+ "+∞",
+ "NaN",
+ ],
+];
+
+for (const [signDisplay, ...expected] of tests) {
+ const nf = new Intl.NumberFormat("ko-KR", {signDisplay});
+ assert.sameValue(nf.format(-Infinity), expected[0], `-Infinity (${signDisplay})`);
+ assert.sameValue(nf.format(-987), expected[1], `-987 (${signDisplay})`);
+ assert.sameValue(nf.format(-0.0001), expected[2], `-0.0001 (${signDisplay})`);
+ assert.sameValue(nf.format(-0), expected[3], `-0 (${signDisplay})`);
+ assert.sameValue(nf.format(0), expected[4], `0 (${signDisplay})`);
+ assert.sameValue(nf.format(0.0001), expected[5], `0.0001 (${signDisplay})`);
+ assert.sameValue(nf.format(987), expected[6], `987 (${signDisplay})`);
+ assert.sameValue(nf.format(Infinity), expected[7], `Infinity (${signDisplay})`);
+ assert.sameValue(nf.format(NaN), expected[8], `NaN (${signDisplay})`);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-de-DE.js
new file mode 100644
index 0000000000..5f46d481f0
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-de-DE.js
@@ -0,0 +1,19 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [de-DE]
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat("de-DE", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" });
+assert.sameValue(nf.format(-987), "-987,00 $");
+assert.sameValue(nf.format(-0.0001), "0,00 $");
+assert.sameValue(nf.format(-0), "0,00 $");
+assert.sameValue(nf.format(0), "0,00 $");
+assert.sameValue(nf.format(0.0001), "0,00 $");
+assert.sameValue(nf.format(987), "987,00 $");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-en-US.js
new file mode 100644
index 0000000000..6fca2adf6b
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-en-US.js
@@ -0,0 +1,19 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [en-US]
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" });
+assert.sameValue(nf.format(-987), "($987.00)");
+assert.sameValue(nf.format(-0.0001), "$0.00");
+assert.sameValue(nf.format(-0), "$0.00");
+assert.sameValue(nf.format(0), "$0.00");
+assert.sameValue(nf.format(0.0001), "$0.00");
+assert.sameValue(nf.format(987), "$987.00");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-ja-JP.js
new file mode 100644
index 0000000000..8485f7111e
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-ja-JP.js
@@ -0,0 +1,19 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [ja-JP]
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat("ja-JP", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" });
+assert.sameValue(nf.format(-987), "($987.00)");
+assert.sameValue(nf.format(-0.0001), "$0.00");
+assert.sameValue(nf.format(-0), "$0.00");
+assert.sameValue(nf.format(0), "$0.00");
+assert.sameValue(nf.format(0.0001), "$0.00");
+assert.sameValue(nf.format(987), "$987.00");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-ko-KR.js
new file mode 100644
index 0000000000..f5776b42a7
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-ko-KR.js
@@ -0,0 +1,19 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [ko-KR]
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat("ko-KR", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" });
+assert.sameValue(nf.format(-987), "(US$987.00)");
+assert.sameValue(nf.format(-0.0001), "US$0.00");
+assert.sameValue(nf.format(-0), "US$0.00");
+assert.sameValue(nf.format(0), "US$0.00");
+assert.sameValue(nf.format(0.0001), "US$0.00");
+assert.sameValue(nf.format(987), "US$987.00");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-zh-TW.js
new file mode 100644
index 0000000000..1ef08d0665
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-currency-zh-TW.js
@@ -0,0 +1,19 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [zh-TW]
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat("zh-TW", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" });
+assert.sameValue(nf.format(-987), "(US$987.00)");
+assert.sameValue(nf.format(-0.0001), "US$0.00");
+assert.sameValue(nf.format(-0), "US$0.00");
+assert.sameValue(nf.format(0), "US$0.00");
+assert.sameValue(nf.format(0.0001), "US$0.00");
+assert.sameValue(nf.format(987), "US$987.00");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-de-DE.js
new file mode 100644
index 0000000000..1433dc09be
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-de-DE.js
@@ -0,0 +1,22 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [de-DE]
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat("de-DE", {signDisplay: "negative"});
+assert.sameValue(nf.format(-Infinity), "-∞", "-Infinity");
+assert.sameValue(nf.format(-987), "-987", "-987");
+assert.sameValue(nf.format(-0.0001), "0", "-0.0001");
+assert.sameValue(nf.format(-0), "0", "-0");
+assert.sameValue(nf.format(0), "0", "0");
+assert.sameValue(nf.format(0.0001), "0", "0.0001");
+assert.sameValue(nf.format(987), "987", "987");
+assert.sameValue(nf.format(Infinity), "∞", "Infinity");
+assert.sameValue(nf.format(NaN), "NaN", "NaN");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-en-US.js
new file mode 100644
index 0000000000..84cef9d244
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-en-US.js
@@ -0,0 +1,22 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [en-US]
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat("en-US", {signDisplay: "negative"});
+assert.sameValue(nf.format(-Infinity), "-∞", "-Infinity");
+assert.sameValue(nf.format(-987), "-987", "-987");
+assert.sameValue(nf.format(-0.0001), "0", "-0.0001");
+assert.sameValue(nf.format(-0), "0", "-0");
+assert.sameValue(nf.format(0), "0", "0");
+assert.sameValue(nf.format(0.0001), "0", "0.0001");
+assert.sameValue(nf.format(987), "987", "987");
+assert.sameValue(nf.format(Infinity), "∞", "Infinity");
+assert.sameValue(nf.format(NaN), "NaN", "NaN");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-ja-JP.js
new file mode 100644
index 0000000000..1b018cb1da
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-ja-JP.js
@@ -0,0 +1,22 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [ja-JP]
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat("ja-JP", {signDisplay: "negative"});
+assert.sameValue(nf.format(-Infinity), "-∞", "-Infinity");
+assert.sameValue(nf.format(-987), "-987", "-987");
+assert.sameValue(nf.format(-0.0001), "0", "-0.0001");
+assert.sameValue(nf.format(-0), "0", "-0");
+assert.sameValue(nf.format(0), "0", "0");
+assert.sameValue(nf.format(0.0001), "0", "0.0001");
+assert.sameValue(nf.format(987), "987", "987");
+assert.sameValue(nf.format(Infinity), "∞", "Infinity");
+assert.sameValue(nf.format(NaN), "NaN", "NaN");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-ko-KR.js
new file mode 100644
index 0000000000..c8cff2890f
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-ko-KR.js
@@ -0,0 +1,22 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [ko-KR]
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat("ko-KR", {signDisplay: "negative"});
+assert.sameValue(nf.format(-Infinity), "-∞", "-Infinity");
+assert.sameValue(nf.format(-987), "-987", "-987");
+assert.sameValue(nf.format(-0.0001), "0", "-0.0001");
+assert.sameValue(nf.format(-0), "0", "-0");
+assert.sameValue(nf.format(0), "0", "0");
+assert.sameValue(nf.format(0.0001), "0", "0.0001");
+assert.sameValue(nf.format(987), "987", "987");
+assert.sameValue(nf.format(Infinity), "∞", "Infinity");
+assert.sameValue(nf.format(NaN), "NaN", "NaN");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-zh-TW.js
new file mode 100644
index 0000000000..aadc9e35eb
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-negative-zh-TW.js
@@ -0,0 +1,22 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [zh-TW]
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat("zh-TW", {signDisplay: "negative"});
+assert.sameValue(nf.format(-Infinity), "-∞", "-Infinity");
+assert.sameValue(nf.format(-987), "-987", "-987");
+assert.sameValue(nf.format(-0.0001), "0", "-0.0001");
+assert.sameValue(nf.format(-0), "0", "-0");
+assert.sameValue(nf.format(0), "0", "0");
+assert.sameValue(nf.format(0.0001), "0", "0.0001");
+assert.sameValue(nf.format(987), "987", "987");
+assert.sameValue(nf.format(Infinity), "∞", "Infinity");
+assert.sameValue(nf.format(NaN), "非數值", "NaN");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-rounding.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-rounding.js
new file mode 100644
index 0000000000..726231f81d
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-rounding.js
@@ -0,0 +1,20 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [en-US]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const fmt = new Intl.NumberFormat("en-US", {
+ maximumFractionDigits: 1,
+ signDisplay: "exceptZero"
+});
+
+assert.sameValue(fmt.format(0.01), "0");
+assert.sameValue(fmt.format(-0.01), "0");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-zh-TW.js
new file mode 100644
index 0000000000..c16fa79c86
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-zh-TW.js
@@ -0,0 +1,77 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [zh-TW]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ "auto",
+ "-∞",
+ "-987",
+ "-0",
+ "-0",
+ "0",
+ "0",
+ "987",
+ "∞",
+ "非數值",
+ ],
+ [
+ "always",
+ "-∞",
+ "-987",
+ "-0",
+ "-0",
+ "+0",
+ "+0",
+ "+987",
+ "+∞",
+ "+非數值",
+ ],
+ [
+ "never",
+ "∞",
+ "987",
+ "0",
+ "0",
+ "0",
+ "0",
+ "987",
+ "∞",
+ "非數值",
+ ],
+ [
+ "exceptZero",
+ "-∞",
+ "-987",
+ "0",
+ "0",
+ "0",
+ "0",
+ "+987",
+ "+∞",
+ "非數值",
+ ],
+];
+
+for (const [signDisplay, ...expected] of tests) {
+ const nf = new Intl.NumberFormat("zh-TW", {signDisplay});
+ assert.sameValue(nf.format(-Infinity), expected[0], `-Infinity (${signDisplay})`);
+ assert.sameValue(nf.format(-987), expected[1], `-987 (${signDisplay})`);
+ assert.sameValue(nf.format(-0.0001), expected[2], `-0.0001 (${signDisplay})`);
+ assert.sameValue(nf.format(-0), expected[3], `-0 (${signDisplay})`);
+ assert.sameValue(nf.format(0), expected[4], `0 (${signDisplay})`);
+ assert.sameValue(nf.format(0.0001), expected[5], `0.0001 (${signDisplay})`);
+ assert.sameValue(nf.format(987), expected[6], `987 (${signDisplay})`);
+ assert.sameValue(nf.format(Infinity), expected[7], `Infinity (${signDisplay})`);
+ assert.sameValue(nf.format(NaN), expected[8], `NaN (${signDisplay})`);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/this-value-not-numberformat.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/this-value-not-numberformat.js
new file mode 100644
index 0000000000..bb20845bc9
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/this-value-not-numberformat.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2018 Ujjwal Sharma. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: >
+ Tests that Intl.NumberFormat.prototype.format throws a TypeError
+ if called on a non-object value or an object that hasn't been
+ initialized as a NumberFormat.
+---*/
+
+const invalidTargets = [undefined, null, true, 0, 'NumberFormat', [], {}, Symbol()];
+const fn = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, 'format').get;
+
+invalidTargets.forEach(target => {
+ assert.throws(
+ TypeError,
+ () => fn.call(target),
+ `Calling format getter on ${String(target)} should throw a TypeError.`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-de-DE.js
new file mode 100644
index 0000000000..622496c60c
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-de-DE.js
@@ -0,0 +1,71 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the unit style.
+locale: [de-DE]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ -987,
+ {
+ "short": "-987 km/h",
+ "narrow": "-987 km/h",
+ "long": "-987 Kilometer pro Stunde",
+ }
+ ],
+ [
+ -0.001,
+ {
+ "short": "-0,001 km/h",
+ "narrow": "-0,001 km/h",
+ "long": "-0,001 Kilometer pro Stunde",
+ }
+ ],
+ [
+ -0,
+ {
+ "short": "-0 km/h",
+ "narrow": "-0 km/h",
+ "long": "-0 Kilometer pro Stunde",
+ }
+ ],
+ [
+ 0,
+ {
+ "short": "0 km/h",
+ "narrow": "0 km/h",
+ "long": "0 Kilometer pro Stunde",
+ }
+ ],
+ [
+ 0.001,
+ {
+ "short": "0,001 km/h",
+ "narrow": "0,001 km/h",
+ "long": "0,001 Kilometer pro Stunde",
+ }
+ ],
+ [
+ 987,
+ {
+ "short": "987 km/h",
+ "narrow": "987 km/h",
+ "long": "987 Kilometer pro Stunde",
+ }
+ ],
+];
+
+for (const [number, expectedData] of tests) {
+ for (const [unitDisplay, expected] of Object.entries(expectedData)) {
+ const nf = new Intl.NumberFormat("de-DE", { style: "unit", unit: "kilometer-per-hour", unitDisplay });
+ assert.sameValue(nf.format(number), expected);
+ }
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-en-US.js
new file mode 100644
index 0000000000..a0d053da30
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-en-US.js
@@ -0,0 +1,71 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the unit style.
+locale: [en-US]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ -987,
+ {
+ "short": "-987 km/h",
+ "narrow": "-987km/h",
+ "long": "-987 kilometers per hour",
+ }
+ ],
+ [
+ -0.001,
+ {
+ "short": "-0.001 km/h",
+ "narrow": "-0.001km/h",
+ "long": "-0.001 kilometers per hour",
+ }
+ ],
+ [
+ -0,
+ {
+ "short": "-0 km/h",
+ "narrow": "-0km/h",
+ "long": "-0 kilometers per hour",
+ }
+ ],
+ [
+ 0,
+ {
+ "short": "0 km/h",
+ "narrow": "0km/h",
+ "long": "0 kilometers per hour",
+ }
+ ],
+ [
+ 0.001,
+ {
+ "short": "0.001 km/h",
+ "narrow": "0.001km/h",
+ "long": "0.001 kilometers per hour",
+ }
+ ],
+ [
+ 987,
+ {
+ "short": "987 km/h",
+ "narrow": "987km/h",
+ "long": "987 kilometers per hour",
+ }
+ ],
+];
+
+for (const [number, expectedData] of tests) {
+ for (const [unitDisplay, expected] of Object.entries(expectedData)) {
+ const nf = new Intl.NumberFormat("en-US", { style: "unit", unit: "kilometer-per-hour", unitDisplay });
+ assert.sameValue(nf.format(number), expected);
+ }
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-ja-JP.js
new file mode 100644
index 0000000000..2fc6c38a37
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-ja-JP.js
@@ -0,0 +1,71 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the unit style.
+locale: [ja-JP]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ -987,
+ {
+ "short": "-987 km/h",
+ "narrow": "-987km/h",
+ "long": "時速 -987 キロメートル",
+ }
+ ],
+ [
+ -0.001,
+ {
+ "short": "-0.001 km/h",
+ "narrow": "-0.001km/h",
+ "long": "時速 -0.001 キロメートル",
+ }
+ ],
+ [
+ -0,
+ {
+ "short": "-0 km/h",
+ "narrow": "-0km/h",
+ "long": "時速 -0 キロメートル",
+ }
+ ],
+ [
+ 0,
+ {
+ "short": "0 km/h",
+ "narrow": "0km/h",
+ "long": "時速 0 キロメートル",
+ }
+ ],
+ [
+ 0.001,
+ {
+ "short": "0.001 km/h",
+ "narrow": "0.001km/h",
+ "long": "時速 0.001 キロメートル",
+ }
+ ],
+ [
+ 987,
+ {
+ "short": "987 km/h",
+ "narrow": "987km/h",
+ "long": "時速 987 キロメートル",
+ }
+ ],
+];
+
+for (const [number, expectedData] of tests) {
+ for (const [unitDisplay, expected] of Object.entries(expectedData)) {
+ const nf = new Intl.NumberFormat("ja-JP", { style: "unit", unit: "kilometer-per-hour", unitDisplay });
+ assert.sameValue(nf.format(number), expected);
+ }
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-ko-KR.js
new file mode 100644
index 0000000000..a7f8e7a908
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-ko-KR.js
@@ -0,0 +1,71 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the unit style.
+locale: [ko-KR]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ -987,
+ {
+ "short": "-987km/h",
+ "narrow": "-987km/h",
+ "long": "시속 -987킬로미터",
+ }
+ ],
+ [
+ -0.001,
+ {
+ "short": "-0.001km/h",
+ "narrow": "-0.001km/h",
+ "long": "시속 -0.001킬로미터",
+ }
+ ],
+ [
+ -0,
+ {
+ "short": "-0km/h",
+ "narrow": "-0km/h",
+ "long": "시속 -0킬로미터",
+ }
+ ],
+ [
+ 0,
+ {
+ "short": "0km/h",
+ "narrow": "0km/h",
+ "long": "시속 0킬로미터",
+ }
+ ],
+ [
+ 0.001,
+ {
+ "short": "0.001km/h",
+ "narrow": "0.001km/h",
+ "long": "시속 0.001킬로미터",
+ }
+ ],
+ [
+ 987,
+ {
+ "short": "987km/h",
+ "narrow": "987km/h",
+ "long": "시속 987킬로미터",
+ }
+ ],
+];
+
+for (const [number, expectedData] of tests) {
+ for (const [unitDisplay, expected] of Object.entries(expectedData)) {
+ const nf = new Intl.NumberFormat("ko-KR", { style: "unit", unit: "kilometer-per-hour", unitDisplay });
+ assert.sameValue(nf.format(number), expected);
+ }
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-zh-TW.js
new file mode 100644
index 0000000000..e3c715a30e
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-zh-TW.js
@@ -0,0 +1,71 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of the unit style.
+locale: [zh-TW]
+features: [Intl.NumberFormat-unified]
+---*/
+
+
+const tests = [
+ [
+ -987,
+ {
+ "short": "-987 公里/小時",
+ "narrow": "-987公里/小時",
+ "long": "每小時 -987 公里",
+ }
+ ],
+ [
+ -0.001,
+ {
+ "short": "-0.001 公里/小時",
+ "narrow": "-0.001公里/小時",
+ "long": "每小時 -0.001 公里",
+ }
+ ],
+ [
+ -0,
+ {
+ "short": "-0 公里/小時",
+ "narrow": "-0公里/小時",
+ "long": "每小時 -0 公里",
+ }
+ ],
+ [
+ 0,
+ {
+ "short": "0 公里/小時",
+ "narrow": "0公里/小時",
+ "long": "每小時 0 公里",
+ }
+ ],
+ [
+ 0.001,
+ {
+ "short": "0.001 公里/小時",
+ "narrow": "0.001公里/小時",
+ "long": "每小時 0.001 公里",
+ }
+ ],
+ [
+ 987,
+ {
+ "short": "987 公里/小時",
+ "narrow": "987公里/小時",
+ "long": "每小時 987 公里",
+ }
+ ],
+];
+
+for (const [number, expectedData] of tests) {
+ for (const [unitDisplay, expected] of Object.entries(expectedData)) {
+ const nf = new Intl.NumberFormat("zh-TW", { style: "unit", unit: "kilometer-per-hour", unitDisplay });
+ assert.sameValue(nf.format(number), expected);
+ }
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/units-invalid.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/units-invalid.js
new file mode 100644
index 0000000000..904cf29ed9
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/units-invalid.js
@@ -0,0 +1,110 @@
+// Copyright 2019 Igalia, S.L., Google, Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of units.
+features: [Intl.NumberFormat-unified]
+---*/
+
+const units = [
+ "acre-foot",
+ "ampere",
+ "arc-minute",
+ "arc-second",
+ "astronomical-unit",
+ "atmosphere",
+ "bushel",
+ "calorie",
+ "carat",
+ "centiliter",
+ "century",
+ "cubic-centimeter",
+ "cubic-foot",
+ "cubic-inch",
+ "cubic-kilometer",
+ "cubic-meter",
+ "cubic-mile",
+ "cubic-yard",
+ "cup-metric",
+ "cup",
+ "day-person",
+ "deciliter",
+ "decimeter",
+ "fathom",
+ "foodcalorie",
+ "furlong",
+ "g-force",
+ "gallon-imperial",
+ "generic",
+ "gigahertz",
+ "gigawatt",
+ "hectoliter",
+ "hectopascal",
+ "hertz",
+ "horsepower",
+ "inch-hg",
+ "joule",
+ "karat",
+ "kelvin",
+ "kilocalorie",
+ "kilohertz",
+ "kilojoule",
+ "kilowatt-hour",
+ "kilowatt",
+ "knot",
+ "light-year",
+ "lux",
+ "megahertz",
+ "megaliter",
+ "megawatt",
+ "metric-ton",
+ "microgram",
+ "micrometer",
+ "milliampere",
+ "millibar",
+ "milligram",
+ "millimeter-of-mercury",
+ "milliwatt",
+ "month-person",
+ "nanometer",
+ "nautical-mile",
+ "ohm",
+ "ounce-troy",
+ "parsec",
+ "permille",
+ "picometer",
+ "pint-metric",
+ "pint",
+ "point",
+ "quart",
+ "radian",
+ "revolution",
+ "square-centimeter",
+ "square-foot",
+ "square-inch",
+ "square-kilometer",
+ "square-meter",
+ "square-mile",
+ "square-yard",
+ "tablespoon",
+ "teaspoon",
+ "ton",
+ "volt",
+ "watt",
+ "week-person",
+ "year-person",
+ "liter-per-100kilometers",
+ "meter-per-second-squared",
+ "mile-per-gallon-imperial",
+ "milligram-per-deciliter",
+ "millimole-per-liter",
+ "part-per-million",
+ "pound-per-square-inch",
+];
+
+for (const unit of units) {
+ assert.throws(RangeError, () => new Intl.NumberFormat(undefined, { style: "unit", unit }), `Throw for ${unit}`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/units.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/units.js
new file mode 100644
index 0000000000..8c441008a3
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/units.js
@@ -0,0 +1,27 @@
+// Copyright 2019 Igalia, S.L., Google, Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Checks handling of units.
+includes: [testIntl.js]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function check(unit) {
+ const s1 = (123).toLocaleString(undefined, { style: "unit", unit: unit });
+ const s2 = (123).toLocaleString();
+ assert.notSameValue(s1, s2);
+}
+
+const units = allSimpleSanctionedUnits();
+
+for (const simpleUnit of units) {
+ check(simpleUnit);
+ for (const simpleUnit2 of units) {
+ check(simpleUnit + "-per-" + simpleUnit2);
+ check(simpleUnit2 + "-per-" + simpleUnit);
+ }
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-de-DE.js
new file mode 100644
index 0000000000..a2368e2d21
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-de-DE.js
@@ -0,0 +1,33 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: |
+ Checks handling of the useGrouping option to the NumberFormat constructor.
+locale: [de-DE]
+---*/
+
+var nf;
+
+nf = new Intl.NumberFormat('de-DE', {});
+
+assert.sameValue(nf.format(100), '100', '(omitted)');
+assert.sameValue(nf.format(1000), '1.000', '(omitted)');
+assert.sameValue(nf.format(10000), '10.000', '(omitted)');
+assert.sameValue(nf.format(100000), '100.000', '(omitted)');
+
+nf = new Intl.NumberFormat('de-DE', {useGrouping: true});
+
+assert.sameValue(nf.format(100), '100', 'true');
+assert.sameValue(nf.format(1000), '1.000', 'true');
+assert.sameValue(nf.format(100000), '100.000', 'true');
+
+nf = new Intl.NumberFormat('de-DE', {useGrouping: false});
+
+assert.sameValue(nf.format(100), '100', 'false');
+assert.sameValue(nf.format(1000), '1000', 'false');
+assert.sameValue(nf.format(10000), '10000', 'false');
+assert.sameValue(nf.format(100000), '100000', 'false');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-en-IN.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-en-IN.js
new file mode 100644
index 0000000000..29bc42b207
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-en-IN.js
@@ -0,0 +1,34 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: |
+ Checks handling of the useGrouping option to the NumberFormat constructor.
+locale: [en-IN]
+---*/
+
+var nf;
+
+nf = new Intl.NumberFormat('en-IN', {});
+
+assert.sameValue(nf.format(100), '100', '(omitted)');
+assert.sameValue(nf.format(1000), '1,000', '(omitted)');
+assert.sameValue(nf.format(10000), '10,000', '(omitted)');
+assert.sameValue(nf.format(100000), '1,00,000', '(omitted)');
+
+nf = new Intl.NumberFormat('en-IN', {useGrouping: true});
+
+assert.sameValue(nf.format(100), '100', 'true');
+assert.sameValue(nf.format(1000), '1,000', 'true');
+assert.sameValue(nf.format(10000), '10,000', 'true');
+assert.sameValue(nf.format(100000), '1,00,000', 'true');
+
+nf = new Intl.NumberFormat('en-IN', {useGrouping: false});
+
+assert.sameValue(nf.format(100), '100', 'false');
+assert.sameValue(nf.format(1000), '1000', 'false');
+assert.sameValue(nf.format(10000), '10000', 'false');
+assert.sameValue(nf.format(100000), '100000', 'false');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-en-US.js
new file mode 100644
index 0000000000..3baaafb8bc
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-en-US.js
@@ -0,0 +1,34 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: |
+ Checks handling of the useGrouping option to the NumberFormat constructor.
+locale: [en-US]
+---*/
+
+var nf;
+
+nf = new Intl.NumberFormat('en-US', {});
+
+assert.sameValue(nf.format(100), '100', '(omitted)');
+assert.sameValue(nf.format(1000), '1,000', '(omitted)');
+assert.sameValue(nf.format(10000), '10,000', '(omitted)');
+assert.sameValue(nf.format(100000), '100,000', '(omitted)');
+
+nf = new Intl.NumberFormat('en-US', {useGrouping: true});
+
+assert.sameValue(nf.format(100), '100', 'true');
+assert.sameValue(nf.format(1000), '1,000', 'true');
+assert.sameValue(nf.format(10000), '10,000', 'true');
+assert.sameValue(nf.format(100000), '100,000', 'true');
+
+nf = new Intl.NumberFormat('en-US', {useGrouping: false});
+
+assert.sameValue(nf.format(100), '100', 'false');
+assert.sameValue(nf.format(1000), '1000', 'false');
+assert.sameValue(nf.format(10000), '10000', 'false');
+assert.sameValue(nf.format(100000), '100000', 'false');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-de-DE.js
new file mode 100644
index 0000000000..eb7270ac2b
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-de-DE.js
@@ -0,0 +1,35 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: |
+ Checks handling of the useGrouping option to the NumberFormat constructor.
+locale: [de-DE]
+features: [Intl.NumberFormat-v3]
+---*/
+
+var nf;
+
+nf = new Intl.NumberFormat('de-DE', {useGrouping: 'always'});
+
+assert.sameValue(nf.format(100), '100', '"always"');
+assert.sameValue(nf.format(1000), '1.000', '"always"');
+assert.sameValue(nf.format(10000), '10.000', '"always"');
+assert.sameValue(nf.format(100000), '100.000', '"always"');
+
+nf = new Intl.NumberFormat('de-DE', {useGrouping: 'min2'});
+
+assert.sameValue(nf.format(100), '100', '"min2"');
+assert.sameValue(nf.format(1000), '1000', '"min2"');
+assert.sameValue(nf.format(10000), '10.000', '"min2"');
+assert.sameValue(nf.format(100000), '100.000', '"min2"');
+
+nf = new Intl.NumberFormat('de-DE', {notation: 'compact'});
+
+assert.sameValue(nf.format(100), '100', 'notation: "compact"');
+assert.sameValue(nf.format(1000), '1000', 'notation: "compact"');
+assert.sameValue(nf.format(10000), '10.000', 'notation: "compact"');
+assert.sameValue(nf.format(100000), '100.000', 'notation: "compact"');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-en-IN.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-en-IN.js
new file mode 100644
index 0000000000..34445338e2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-en-IN.js
@@ -0,0 +1,35 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: |
+ Checks handling of the useGrouping option to the NumberFormat constructor.
+locale: [en-IN]
+features: [Intl.NumberFormat-v3]
+---*/
+
+var nf;
+
+nf = new Intl.NumberFormat('en-IN', {useGrouping: 'always'});
+
+assert.sameValue(nf.format(100), '100', '"always"');
+assert.sameValue(nf.format(1000), '1,000', '"always"');
+assert.sameValue(nf.format(10000), '10,000', '"always"');
+assert.sameValue(nf.format(100000), '1,00,000', '"always"');
+
+nf = new Intl.NumberFormat('en-IN', {useGrouping: 'min2'});
+
+assert.sameValue(nf.format(100), '100', '"min2"');
+assert.sameValue(nf.format(1000), '1000', '"min2"');
+assert.sameValue(nf.format(10000), '10,000', '"min2"');
+assert.sameValue(nf.format(100000), '1,00,000', '"min2"');
+
+nf = new Intl.NumberFormat('en-IN', {notation: 'compact'});
+
+assert.sameValue(nf.format(100), '100', 'notation: "compact"');
+assert.sameValue(nf.format(1000), '1T', 'notation: "compact"');
+assert.sameValue(nf.format(10000), '10T', 'notation: "compact"');
+assert.sameValue(nf.format(100000), '1L', 'notation: "compact"');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-en-US.js
new file mode 100644
index 0000000000..0846461275
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/useGrouping-extended-en-US.js
@@ -0,0 +1,35 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: |
+ Checks handling of the useGrouping option to the NumberFormat constructor.
+locale: [en-US]
+features: [Intl.NumberFormat-v3]
+---*/
+
+var nf;
+
+nf = new Intl.NumberFormat('en-US', {useGrouping: 'always'});
+
+assert.sameValue(nf.format(100), '100', '"always"');
+assert.sameValue(nf.format(1000), '1,000', '"always"');
+assert.sameValue(nf.format(10000), '10,000', '"always"');
+assert.sameValue(nf.format(100000), '100,000', '"always"');
+
+nf = new Intl.NumberFormat('en-US', {useGrouping: 'min2'});
+
+assert.sameValue(nf.format(100), '100', '"min2"');
+assert.sameValue(nf.format(1000), '1000', '"min2"');
+assert.sameValue(nf.format(10000), '10,000', '"min2"');
+assert.sameValue(nf.format(100000), '100,000', '"min2"');
+
+nf = new Intl.NumberFormat('en-US', {notation: 'compact'});
+
+assert.sameValue(nf.format(100), '100', 'notation: "compact"');
+assert.sameValue(nf.format(1000), '1K', 'notation: "compact"');
+assert.sameValue(nf.format(10000), '10K', 'notation: "compact"');
+assert.sameValue(nf.format(100000), '100K', 'notation: "compact"');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-arg-coerced-to-number.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-arg-coerced-to-number.js
new file mode 100644
index 0000000000..da25c9c5f0
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-arg-coerced-to-number.js
@@ -0,0 +1,26 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.3.2_1_a_ii
+description: >
+ Tests that Intl.NumberFormat.prototype.format converts other
+ types to numbers.
+author: Roozbeh Pournader
+---*/
+
+var formatter = new Intl.NumberFormat();
+var testData = [undefined, null, true, '0.6666666', {valueOf: function () { return '0.1234567';}}];
+var number;
+var i, input, correctResult, result;
+
+for (i in testData) {
+ input = testData[i];
+ number = +input;
+ correctResult = formatter.format(number);
+
+ result = formatter.format(input);
+ assert.sameValue(result, correctResult, 'Intl.NumberFormat does not convert other types to numbers. Input: "' + input + '".');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-decimal-string.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-decimal-string.js
new file mode 100644
index 0000000000..f80bc2fb9b
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-decimal-string.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-number-format-functions
+description: >
+ Intl.NumberFormat.prototype.format converts its argument (called value) to a
+ number using ToIntlMathematicalValue.
+features: [Intl.NumberFormat-v3]
+locale: [en-US]
+---*/
+
+var nf = new Intl.NumberFormat('en-US', {maximumFractionDigits: 20});
+
+// The value 100,000 should only be interpreted as infinity if the input is the
+// string "Infinity".
+assert.sameValue(nf.format('100000'), '100,000');
+// The value -100,000 should only be interpreted as negative infinity if the
+// input is the string "-Infinity".
+assert.sameValue(nf.format('-100000'), '-100,000');
+
+assert.sameValue(nf.format('1.0000000000000001'), '1.0000000000000001');
+assert.sameValue(nf.format('-1.0000000000000001'), '-1.0000000000000001');
+assert.sameValue(nf.format('987654321987654321'), '987,654,321,987,654,321');
+assert.sameValue(nf.format('-987654321987654321'), '-987,654,321,987,654,321');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-tonumber.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-tonumber.js
new file mode 100644
index 0000000000..3785b29103
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-tonumber.js
@@ -0,0 +1,46 @@
+// Copyright (C) 2018 Ujjwal Sharma. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-number-format-functions
+description: >
+ Tests that Intl.NumberFormat.prototype.format converts its argument
+ (called value) to a number using ToNumber (7.1.3).
+info: |
+ 11.1.4Number Format Functions
+
+ 4. Let x be ? ToNumber(value).
+features: [Symbol]
+---*/
+
+const toNumberResults = [
+ [undefined, NaN],
+ [null, +0],
+ [true, 1],
+ [false, 0],
+ ['42', 42],
+ ['foo', NaN],
+ ['Infinity', Infinity],
+ ['-Infinity', -Infinity]
+];
+
+const nf = new Intl.NumberFormat();
+
+toNumberResults.forEach(pair => {
+ const [value, result] = pair;
+ assert.sameValue(nf.format(value), nf.format(result));
+});
+
+let count = 0;
+const dummy = {};
+dummy[Symbol.toPrimitive] = hint => (hint === 'number' ? ++count : NaN);
+assert.sameValue(nf.format(dummy), nf.format(count));
+assert.sameValue(count, 1);
+
+assert.throws(
+ TypeError,
+ () => nf.format(Symbol()),
+ "ToNumber(arg) throws a TypeError when arg is of type 'Symbol'"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/argument-to-Intlmathematicalvalue-throws.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/argument-to-Intlmathematicalvalue-throws.js
new file mode 100644
index 0000000000..46d6f63e31
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/argument-to-Intlmathematicalvalue-throws.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat-formatRange
+description: >
+ "formatRange" basic tests when argument cannot be converted using ToIntlMathematicalValue
+info: |
+ Intl.NumberFormat.prototype.formatRange( start, end )
+ (...)
+ 4. Let x be ? ToIntlMathematicalValue(start).
+ 5. Let y be ? ToIntlMathematicalValue(end).
+features: [Intl.NumberFormat-v3]
+---*/
+
+
+const nf = new Intl.NumberFormat();
+
+// Throw if arguments cannot be cast using the method ToIntlMathematicalValue
+assert.throws(TypeError, () => { nf.formatRange(Symbol(102), 201) });
+assert.throws(TypeError, () => { nf.formatRange(102,Symbol(201)) });
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/browser.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/browser.js
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/builtin.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/builtin.js
new file mode 100644
index 0000000000..91baf121e3
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/builtin.js
@@ -0,0 +1,31 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-ecmascript-standard-built-in-objects
+description: >
+ Tests that the Intl.NumberFormat.prototype.formatRange function meets the
+ requirements for built-in objects defined by the ECMAScript Language
+ Specification.
+includes: [isConstructor.js]
+features: [Reflect.construct,Intl.NumberFormat-v3]
+---*/
+
+const formatRange = Intl.NumberFormat.prototype.formatRange;
+
+assert.sameValue(Object.prototype.toString.call(formatRange), "[object Function]",
+ "The [[Class]] internal property of a built-in function must be " +
+ "\"Function\".");
+
+assert(Object.isExtensible(formatRange),
+ "Built-in objects must be extensible.");
+
+assert.sameValue(Object.getPrototypeOf(formatRange), Function.prototype);
+
+assert.sameValue(formatRange.hasOwnProperty("prototype"), false,
+ "Built-in functions that aren't constructors must not have a prototype property.");
+
+assert.sameValue(isConstructor(formatRange), false,
+ "Built-in functions don't implement [[Construct]] unless explicitly specified.");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/en-US.js
new file mode 100644
index 0000000000..9eabe00c26
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/en-US.js
@@ -0,0 +1,39 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat-formatRange
+description: Basic tests for the en-US output of formatRange()
+locale: [en-US]
+features: [Intl.NumberFormat-v3]
+---*/
+
+// Basic example test en-US
+const nf = new Intl.NumberFormat("en-US", {
+ style: "currency",
+ currency: "USD",
+ maximumFractionDigits: 0,
+});
+
+assert.sameValue(nf.formatRange(3, 5), "$3 – $5");
+assert.sameValue(nf.formatRange(2.9, 3.1), "~$3");
+
+
+// Basic example test en-US using signDisplay to always
+const nf2 = new Intl.NumberFormat("en-US", {
+ style: "currency",
+ currency: "USD",
+ signDisplay: "always",
+});
+
+assert.sameValue(nf2.formatRange(2.9, 3.1), "+$2.90–3.10");
+
+// Basic example test en-US string formatting
+const nf3 = new Intl.NumberFormat("en-US");
+const string1 = "987654321987654321";
+const string2 = "987654321987654322";
+
+assert.sameValue(nf3.formatRange(string1, string2), "987,654,321,987,654,321–987,654,321,987,654,322");
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/invoked-as-func.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/invoked-as-func.js
new file mode 100644
index 0000000000..b08abc7d26
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/invoked-as-func.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat-NumberFormat
+description: basic tests internal slot initialization and call receiver errors
+info: |
+ Intl.NumberFormat.prototype.formatRange(start, end )
+ (...)
+ 2. Perform ? RequireInternalSlot(nf, [[InitializedNumberFormat]])
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat();
+
+// Perform ? RequireInternalSlot(nf, [[InitializedNumberFormat]])
+let f = nf['formatRange'];
+
+assert.sameValue(typeof f, 'function');
+assert.throws(TypeError, () => { f(1, 23) });
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/length.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/length.js
new file mode 100644
index 0000000000..aefcbeb93e
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/length.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Intl.NumberFormat.prototype.formatRange.length.
+includes: [propertyHelper.js]
+features: [Intl.NumberFormat-v3]
+---*/
+verifyProperty(Intl.NumberFormat.prototype.formatRange, 'length', {
+ value: 2,
+ enumerable: false,
+ writable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/name.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/name.js
new file mode 100644
index 0000000000..ce60f9e67b
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/name.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Intl.NumberFormat.prototype.formatRange.name value and descriptor.
+includes: [propertyHelper.js]
+features: [Intl.NumberFormat-v3]
+---*/
+verifyProperty(Intl.NumberFormat.prototype.formatRange, 'name', {
+ value: 'formatRange',
+ enumerable: false,
+ writable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/nan-arguments-throws.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/nan-arguments-throws.js
new file mode 100644
index 0000000000..c686cb84a2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/nan-arguments-throws.js
@@ -0,0 +1,31 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat-formatRange
+description: >
+ "formatRange" Throws a RangeError if some of arguments is cast to NaN
+info: |
+ Intl.NumberFormat.prototype.formatRange( start, end )
+ (...)
+ 6. Return ? FormatNumericRange(nf, x, y).
+
+ FormatNumericRange( numberFormat, x, y )
+ 1. Let parts be ? PartitionNumberRangePattern(numberFormat, x, y).
+
+ PartitionNumberRangePattern( numberFormat, x, y )
+ 1. If x is NaN or y is NaN, throw a RangeError exception.
+features: [Intl.NumberFormat-v3]
+---*/
+
+
+const nf = new Intl.NumberFormat();
+
+// If x or y is NaN ..., throw a RangeError exception.
+assert.throws(RangeError, () => { nf.formatRange(NaN, 23) });
+assert.throws(RangeError, () => { nf.formatRange(12, NaN) });
+assert.throws(RangeError, () => { nf.formatRange(NaN, -23) });
+assert.throws(RangeError, () => { nf.formatRange(-12, NaN) });
+assert.throws(RangeError, () => { nf.formatRange(NaN, NaN) });
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/prop-desc.js
new file mode 100644
index 0000000000..a0348dc446
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/prop-desc.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Property type and descriptor.
+includes: [propertyHelper.js]
+features: [Intl.NumberFormat-v3]
+---*/
+
+assert.sameValue(
+ typeof Intl.NumberFormat.prototype.formatRange,
+ 'function',
+ '`typeof Intl.NumberFormat.prototype.formatRange` is `function`'
+);
+
+verifyProperty(Intl.NumberFormat.prototype, 'formatRange', {
+ enumerable: false,
+ writable: true,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/pt-PT.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/pt-PT.js
new file mode 100644
index 0000000000..dfb1d4a531
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/pt-PT.js
@@ -0,0 +1,39 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat-formatRange
+description: Basic tests for the pt-PT output of formatRange()
+locale: [pt-PT]
+features: [Intl.NumberFormat-v3]
+---*/
+
+// Basic example test pt-PT
+const nf = new Intl.NumberFormat("pt-PT", {
+ style: "currency",
+ currency: "EUR",
+ maximumFractionDigits: 0,
+});
+
+assert.sameValue(nf.formatRange(3, 5), "3 - 5\u00a0€");
+assert.sameValue(nf.formatRange(2.9, 3.1), "~3\u00a0€");
+
+
+// Basic example test pt-PT using signDisplay to always
+const nf2 = new Intl.NumberFormat("pt-PT", {
+ style: "currency",
+ currency: "EUR",
+ signDisplay: "always",
+});
+
+assert.sameValue(nf2.formatRange(2.9, 3.1), "+2,90 - 3,10\u00a0€");
+
+// Basic example test pt-PT string formatting
+const nf3 = new Intl.NumberFormat("pt-PT");
+const string1 = "987654321987654321";
+const string2 = "987654321987654322";
+
+assert.sameValue(nf3.formatRange(string1, string2), "987\u00a0654\u00a0321\u00a0987\u00a0654\u00a0321 - 987\u00a0654\u00a0321\u00a0987\u00a0654\u00a0322");
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/shell.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/shell.js
@@ -0,0 +1,24 @@
+// GENERATED, DO NOT EDIT
+// file: isConstructor.js
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: |
+ Test if a given function is a constructor function.
+defines: [isConstructor]
+features: [Reflect.construct]
+---*/
+
+function isConstructor(f) {
+ if (typeof f !== "function") {
+ throw new Test262Error("isConstructor invoked with a non-function value");
+ }
+
+ try {
+ Reflect.construct(function(){}, [], f);
+ } catch (e) {
+ return false;
+ }
+ return true;
+}
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/undefined-arguments-throws.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/undefined-arguments-throws.js
new file mode 100644
index 0000000000..a9fbd4f712
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/undefined-arguments-throws.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat.prototype.formatRange
+description: >
+ "formatRange" basic tests when arguments are undefined throw a TypeError exception.
+info: |
+ Intl.NumberFormat.prototype.formatRange ( start, end )
+ (...)
+ 3. If start is undefined or end is undefined, throw a TypeError exception.
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat();
+
+// If arguments are undefined throw a TypeError exception.
+assert.throws(TypeError, () => { nf.formatRange(undefined, 23) });
+assert.throws(TypeError, () => { nf.formatRange(1,undefined) });
+assert.throws(TypeError, () => { nf.formatRange(undefined, undefined)});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/x-greater-than-y-not-throws.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/x-greater-than-y-not-throws.js
new file mode 100644
index 0000000000..42cb8e1c66
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRange/x-greater-than-y-not-throws.js
@@ -0,0 +1,49 @@
+// Copyright 2022 Google, Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat.prototype.formatRange
+description: >
+ "formatRange" basic tests when argument x > y, BigInt included and covers PartitionNumberRangePattern return a string.
+info: |
+ 1.1.21 PartitionNumberRangePattern( numberFormat, x, y )
+ (...)
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat();
+
+// If x > y, return a string.
+assert.sameValue(typeof nf.formatRange(23, 12), "string",
+ "should return string not throw RangeError");
+
+// If x > y, return a string and both x and y are bigint.
+assert.sameValue(typeof nf.formatRange(23n, 12n), "string",
+ "should return string not throw RangeError");
+//if y is -∞, return a string.
+assert.sameValue(typeof nf.formatRange(23, -Infinity), "string",
+ "should return string not throw RangeError");
+//if y is -0 and x ≥ 0, return a string.
+assert.sameValue(typeof nf.formatRange(23, -0), "string",
+ "should return string not throw RangeError");
+assert.sameValue(typeof nf.formatRange(0, -0), "string",
+ "should return string not throw RangeError");
+
+// if y is a mathematical value, return a string.
+assert.sameValue(typeof nf.formatRange(Infinity, 23), "string",
+ "should return string not throw RangeError");
+// if y is -∞, return a string.
+assert.sameValue(typeof nf.formatRange(Infinity, -Infinity), "string",
+ "should return string not throw RangeError");
+// if y is -0, return a string.
+assert.sameValue(typeof nf.formatRange(Infinity, -0), "string",
+ "should return string not throw RangeError");
+
+// if y is a mathematical value and y < 0, return a string.
+assert.sameValue(typeof nf.formatRange(-0, -1), "string",
+ "should return string not throw RangeError");
+// if y is -∞, return a string.
+assert.sameValue(typeof nf.formatRange(-0, -Infinity), "string",
+ "should return string not throw RangeError");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/argument-to-Intlmathematicalvalue-throws.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/argument-to-Intlmathematicalvalue-throws.js
new file mode 100644
index 0000000000..ab2f111db7
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/argument-to-Intlmathematicalvalue-throws.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat-formatRangeToParts
+description: >
+ "formatRangeToParts" basic tests when argument cannot be converted using ToIntlMathematicalValue
+info: |
+ Intl.NumberFormat.prototype.formatRangeToParts( start, end )
+ (...)
+ 4. Let x be ? ToIntlMathematicalValue(start).
+ 5. Let y be ? ToIntlMathematicalValue(end).
+features: [Intl.NumberFormat-v3]
+---*/
+
+
+const nf = new Intl.NumberFormat();
+
+// Throw if arguments cannot be cast using the method ToIntlMathematicalValue
+assert.throws(TypeError, () => { nf.formatRangeToParts(Symbol(102), 201) });
+assert.throws(TypeError, () => { nf.formatRangeToParts(102,Symbol(201)) });
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/browser.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/browser.js
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/builtin.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/builtin.js
new file mode 100644
index 0000000000..d39a1c5819
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/builtin.js
@@ -0,0 +1,31 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-ecmascript-standard-built-in-objects
+description: >
+ Tests that the Intl.NumberFormat.prototype.formatRangeToParts function meets the
+ requirements for built-in objects defined by the ECMAScript Language
+ Specification.
+includes: [isConstructor.js]
+features: [Reflect.construct,Intl.NumberFormat-v3]
+---*/
+
+const formatRangeToParts = Intl.NumberFormat.prototype.formatRangeToParts;
+
+assert.sameValue(Object.prototype.toString.call(formatRangeToParts), "[object Function]",
+ "The [[Class]] internal property of a built-in function must be " +
+ "\"Function\".");
+
+assert(Object.isExtensible(formatRangeToParts),
+ "Built-in objects must be extensible.");
+
+assert.sameValue(Object.getPrototypeOf(formatRangeToParts), Function.prototype);
+
+assert.sameValue(formatRangeToParts.hasOwnProperty("prototype"), false,
+ "Built-in functions that aren't constructors must not have a prototype property.");
+
+assert.sameValue(isConstructor(formatRangeToParts), false,
+ "Built-in functions don't implement [[Construct]] unless explicitly specified.");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/en-US.js
new file mode 100644
index 0000000000..a23cd17f40
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/en-US.js
@@ -0,0 +1,67 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat-formatRangeToParts
+description: Basic tests for the en-US output of formatRangeToParts()
+locale: [en-US]
+features: [Intl.NumberFormat-v3]
+includes: [propertyHelper.js]
+---*/
+
+// Utils functions
+function* zip(a, b) {
+ assert.sameValue(a.length, b.length);
+ for (let i = 0; i < a.length; ++i) {
+ yield [i, a[i], b[i]];
+ }
+}
+
+function compare(actual, expected) {
+ for (const [i, actualEntry, expectedEntry] of zip(actual, expected)) {
+ // assertions
+ assert.sameValue(actualEntry.type, expectedEntry.type, `type for entry ${i}`);
+ assert.sameValue(actualEntry.value, expectedEntry.value, `value for entry ${i}`);
+ assert.sameValue(actualEntry.source, expectedEntry.source, `source for entry ${i}`);
+
+ // 1.1.25_4.a Let O be ObjectCreate(%ObjectPrototype%).
+ assert.sameValue(Object.getPrototypeOf(actualEntry), Object.prototype, `prototype for entry ${i}`);
+ // 1.1.25_4.b Perform ! CreateDataPropertyOrThrow(O, "type", part.[[Type]])
+ verifyProperty(actualEntry, 'type', { enumerable: true, writable: true, configurable: true });
+ // 1.1.25_4.c Perform ! CreateDataPropertyOrThrow(O, "value", part.[[Value]]).
+ verifyProperty(actualEntry, 'value', { enumerable: true, writable: true, configurable: true });
+ // 1.1.25_4.d Perform ! CreateDataPropertyOrThrow(O, "source", part.[[Source]]).
+ verifyProperty(actualEntry, 'source', { enumerable: true, writable: true, configurable: true });
+ }
+}
+
+// Basic example test en-US
+const nf = new Intl.NumberFormat("en-US", {
+ style: "currency",
+ currency: "USD",
+ maximumFractionDigits: 0,
+});
+
+compare(nf.formatRangeToParts(3, 5), [
+ {type: "currency", value: "$", source: "startRange"},
+ {type: "integer", value: "3", source: "startRange"},
+ {type: "literal", value: " – ", source: "shared"},
+ {type: "currency", value: "$", source: "endRange"},
+ {type: "integer", value: "5", source: "endRange"}
+]);
+
+compare(nf.formatRangeToParts(1, 1), [
+ {type: 'approximatelySign', value: '~', source: 'shared'},
+ {type: 'currency', value: '$', source: 'shared'},
+ {type: 'integer', value: '1', source: 'shared'}
+]);
+
+compare(nf.formatRangeToParts(2.999, 3.001), [
+ {type: 'approximatelySign', value: '~', source: 'shared'},
+ {type: 'currency', value: '$', source: 'shared'},
+ {type: 'integer', value: '3', source: 'shared'}
+]);
+
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/invoked-as-func.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/invoked-as-func.js
new file mode 100644
index 0000000000..f3e41989b0
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/invoked-as-func.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat-NumberFormat
+description: basic tests internal slot initialization and call receiver errors
+info: |
+ Intl.NumberFormat.prototype.formatRangeToParts ( start, end )
+ (...)
+ 2. Perform ? RequireInternalSlot(nf, [[InitializedNumberFormat]])
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat();
+
+// Perform ? RequireInternalSlot(nf, [[InitializedNumberFormat]])
+let f = nf['formatRangeToParts'];
+
+assert.sameValue(typeof f, 'function');
+assert.throws(TypeError, () => { f(1, 23) });
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/length.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/length.js
new file mode 100644
index 0000000000..9cc15dcc59
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/length.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Intl.NumberFormat.prototype.formatRangeToParts.length.
+includes: [propertyHelper.js]
+features: [Intl.NumberFormat-v3]
+---*/
+verifyProperty(Intl.NumberFormat.prototype.formatRangeToParts, 'length', {
+ value: 2,
+ enumerable: false,
+ writable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/name.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/name.js
new file mode 100644
index 0000000000..425bc569f1
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/name.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Intl.NumberFormat.prototype.formatRangeToParts.name value and descriptor.
+includes: [propertyHelper.js]
+features: [Intl.NumberFormat-v3]
+---*/
+verifyProperty(Intl.NumberFormat.prototype.formatRangeToParts, 'name', {
+ value: 'formatRangeToParts',
+ enumerable: false,
+ writable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/nan-arguments-throws.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/nan-arguments-throws.js
new file mode 100644
index 0000000000..8dacae8be1
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/nan-arguments-throws.js
@@ -0,0 +1,31 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat-formatRangeToParts
+description: >
+ "formatRangeToParts" Throws a RangeError if some of arguments is cast to NaN
+info: |
+ Intl.NumberFormat.prototype.formatRangeToParts( start, end )
+ (...)
+ 6. Return ? FormatNumericRangeToParts(nf, x, y).
+
+ FormatNumericRangeToParts( numberFormat, x, y )
+ 1. Let parts be ? PartitionNumberRangePattern(numberFormat, x, y).
+
+ PartitionNumberRangePattern( numberFormat, x, y )
+ 1. If x is NaN or y is NaN, throw a RangeError exception.
+features: [Intl.NumberFormat-v3]
+---*/
+
+
+const nf = new Intl.NumberFormat();
+
+// If x or y is NaN ..., throw a RangeError exception.
+assert.throws(RangeError, () => { nf.formatRangeToParts(NaN, 23) });
+assert.throws(RangeError, () => { nf.formatRangeToParts(12, NaN) });
+assert.throws(RangeError, () => { nf.formatRangeToParts(NaN, -23) });
+assert.throws(RangeError, () => { nf.formatRangeToParts(-12, NaN) });
+assert.throws(RangeError, () => { nf.formatRangeToParts(NaN, NaN) });
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/prop-desc.js
new file mode 100644
index 0000000000..32f0bd5364
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/prop-desc.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Property type and descriptor.
+includes: [propertyHelper.js]
+features: [Intl.NumberFormat-v3]
+---*/
+
+assert.sameValue(
+ typeof Intl.NumberFormat.prototype.formatRangeToParts,
+ 'function',
+ '`typeof Intl.NumberFormat.prototype.formatRangeToParts` is `function`'
+);
+
+verifyProperty(Intl.NumberFormat.prototype, 'formatRangeToParts', {
+ enumerable: false,
+ writable: true,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/shell.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/shell.js
@@ -0,0 +1,24 @@
+// GENERATED, DO NOT EDIT
+// file: isConstructor.js
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: |
+ Test if a given function is a constructor function.
+defines: [isConstructor]
+features: [Reflect.construct]
+---*/
+
+function isConstructor(f) {
+ if (typeof f !== "function") {
+ throw new Test262Error("isConstructor invoked with a non-function value");
+ }
+
+ try {
+ Reflect.construct(function(){}, [], f);
+ } catch (e) {
+ return false;
+ }
+ return true;
+}
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/undefined-arguments-throws.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/undefined-arguments-throws.js
new file mode 100644
index 0000000000..3906806b5f
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/undefined-arguments-throws.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat.prototype.formatRangeToParts
+description: >
+ "formatRangeToParts" basic tests when arguments are undefined throw a TypeError exception.
+info: |
+ Intl.NumberFormat.prototype.formatRangeToParts ( start, end )
+ (...)
+ 3. If start is undefined or end is undefined, throw a TypeError exception.
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat();
+
+// If arguments are undefined throw a TypeError exception.
+assert.throws(TypeError, () => { nf.formatRangeToParts(undefined, 23) });
+assert.throws(TypeError, () => { nf.formatRangeToParts(1,undefined) });
+assert.throws(TypeError, () => { nf.formatRangeToParts(undefined, undefined)});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/x-greater-than-y-not-throws.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/x-greater-than-y-not-throws.js
new file mode 100644
index 0000000000..f9b49cc604
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatRangeToParts/x-greater-than-y-not-throws.js
@@ -0,0 +1,49 @@
+// Copyright 2022 Google, Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat.prototype.formatRangeToParts
+description: >
+ "formatRangeToParts" basic tests when argument x > y, BigInt included and covers PartitionNumberRangePattern return a object.
+info: |
+ 1.1.21 PartitionNumberRangePattern( numberFormat, x, y )
+ (...)
+features: [Intl.NumberFormat-v3]
+---*/
+
+const nf = new Intl.NumberFormat();
+
+// If x > y, return a object.
+assert.sameValue(typeof nf.formatRangeToParts(23, 12), "object",
+ "should return object not throw RangeError");
+
+// If x > y, return a object and both x and y are bigint.
+assert.sameValue(typeof nf.formatRangeToParts(23n, 12n), "object",
+ "should return object not throw RangeError");
+//if y is -∞, return a object.
+assert.sameValue(typeof nf.formatRangeToParts(23, -Infinity), "object",
+ "should return object not throw RangeError");
+//if y is -0 and x ≥ 0, return a object.
+assert.sameValue(typeof nf.formatRangeToParts(23, -0), "object",
+ "should return object not throw RangeError");
+assert.sameValue(typeof nf.formatRangeToParts(0, -0), "object",
+ "should return object not throw RangeError");
+
+// if y is a mathematical value, return a object.
+assert.sameValue(typeof nf.formatRangeToParts(Infinity, 23), "object",
+ "should return object not throw RangeError");
+// if y is -∞, return a object.
+assert.sameValue(typeof nf.formatRangeToParts(Infinity, -Infinity), "object",
+ "should return object not throw RangeError");
+// if y is -0, return a object.
+assert.sameValue(typeof nf.formatRangeToParts(Infinity, -0), "object",
+ "should return object not throw RangeError");
+
+// if y is a mathematical value and y < 0, return a object.
+assert.sameValue(typeof nf.formatRangeToParts(-0, -1), "object",
+ "should return object not throw RangeError");
+// if y is -∞, return a object.
+assert.sameValue(typeof nf.formatRangeToParts(-0, -Infinity), "object",
+ "should return object not throw RangeError");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/browser.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/browser.js
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/default-parameter.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/default-parameter.js
new file mode 100644
index 0000000000..c2ec726586
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/default-parameter.js
@@ -0,0 +1,44 @@
+// Copyright (C) 2017 Josh Wolfe. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Intl.NumberFormat.prototype.formatToParts called with no parameters
+info: |
+ Intl.NumberFormat.prototype.formatToParts ([ value ])
+
+ 3. If value is not provided, let value be undefined.
+---*/
+
+var nf = new Intl.NumberFormat();
+
+const implicit = nf.formatToParts();
+const explicit = nf.formatToParts(undefined);
+
+// In most locales this is string "NaN", but there are exceptions, cf. "ليس رقم"
+// in Arabic, "epäluku" in Finnish, "не число" in Russian, "son emas" in Uzbek etc.
+const resultNaN = nf.format(NaN);
+const result = [{ type: 'nan', value: resultNaN }];
+
+assert(
+ partsEquals(implicit, explicit),
+ 'formatToParts() should be equivalent to formatToParts(undefined)'
+);
+
+assert(
+ partsEquals(implicit, result),
+ 'Both implicit and explicit calls should have the correct result'
+);
+
+function partsEquals(parts1, parts2) {
+ if (parts1.length !== parts2.length) return false;
+ for (var i = 0; i < parts1.length; i++) {
+ var part1 = parts1[i];
+ var part2 = parts2[i];
+ if (part1.type !== part2.type) return false;
+ if (part1.value !== part2.value) return false;
+ }
+ return true;
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-de-DE.js
new file mode 100644
index 0000000000..b325432203
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-de-DE.js
@@ -0,0 +1,88 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the engineering and scientific notations.
+locale: [de-DE]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ 0.000345,
+ [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"6"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":","},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"4"}],
+ ],
+ [
+ 0.345,
+ [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":","},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"1"}],
+ ],
+ [
+ 3.45,
+ [{"type":"integer","value":"3"},{"type":"decimal","value":","},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":","},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ ],
+ [
+ 34.5,
+ [{"type":"integer","value":"34"},{"type":"decimal","value":","},{"type":"fraction","value":"5"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":","},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"1"}],
+ ],
+ [
+ 543,
+ [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":","},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"2"}],
+ ],
+ [
+ 5430,
+ [{"type":"integer","value":"5"},{"type":"decimal","value":","},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":","},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ ],
+ [
+ 543000,
+ [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":","},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}],
+ ],
+ [
+ 543211.1,
+ [{"type":"integer","value":"543"},{"type":"decimal","value":","},{"type":"fraction","value":"211"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":","},{"type":"fraction","value":"432"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}],
+ ],
+ [
+ -Infinity,
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ ],
+ [
+ Infinity,
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"infinity","value":"∞"}],
+ ],
+ [
+ NaN,
+ [{"type":"nan","value":"NaN"}],
+ [{"type":"nan","value":"NaN"}],
+ ],
+];
+
+for (const [number, engineering, scientific] of tests) {
+ const nfEngineering = (new Intl.NumberFormat("de-DE", { notation: "engineering" }));
+ verifyFormatParts(nfEngineering.formatToParts(number), engineering, `${number} - engineering`);
+ const nfScientific = (new Intl.NumberFormat("de-DE", { notation: "scientific" }));
+ verifyFormatParts(nfScientific.formatToParts(number), scientific, `${number} - scientific`);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-en-US.js
new file mode 100644
index 0000000000..c05ad26852
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-en-US.js
@@ -0,0 +1,88 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the engineering and scientific notations.
+locale: [en-US]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ 0.000345,
+ [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"6"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"4"}],
+ ],
+ [
+ 0.345,
+ [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"1"}],
+ ],
+ [
+ 3.45,
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ ],
+ [
+ 34.5,
+ [{"type":"integer","value":"34"},{"type":"decimal","value":"."},{"type":"fraction","value":"5"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"1"}],
+ ],
+ [
+ 543,
+ [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"2"}],
+ ],
+ [
+ 5430,
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ ],
+ [
+ 543000,
+ [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}],
+ ],
+ [
+ 543211.1,
+ [{"type":"integer","value":"543"},{"type":"decimal","value":"."},{"type":"fraction","value":"211"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"432"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}],
+ ],
+ [
+ -Infinity,
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ ],
+ [
+ Infinity,
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"infinity","value":"∞"}],
+ ],
+ [
+ NaN,
+ [{"type":"nan","value":"NaN"}],
+ [{"type":"nan","value":"NaN"}],
+ ],
+];
+
+for (const [number, engineering, scientific] of tests) {
+ const nfEngineering = (new Intl.NumberFormat("en-US", { notation: "engineering" }));
+ verifyFormatParts(nfEngineering.formatToParts(number), engineering, `${number} - engineering`);
+ const nfScientific = (new Intl.NumberFormat("en-US", { notation: "scientific" }));
+ verifyFormatParts(nfScientific.formatToParts(number), scientific, `${number} - scientific`);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-ja-JP.js
new file mode 100644
index 0000000000..4bf8ecaea7
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-ja-JP.js
@@ -0,0 +1,88 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the engineering and scientific notations.
+locale: [ja-JP]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ 0.000345,
+ [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"6"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"4"}],
+ ],
+ [
+ 0.345,
+ [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"1"}],
+ ],
+ [
+ 3.45,
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ ],
+ [
+ 34.5,
+ [{"type":"integer","value":"34"},{"type":"decimal","value":"."},{"type":"fraction","value":"5"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"1"}],
+ ],
+ [
+ 543,
+ [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"2"}],
+ ],
+ [
+ 5430,
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ ],
+ [
+ 543000,
+ [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}],
+ ],
+ [
+ 543211.1,
+ [{"type":"integer","value":"543"},{"type":"decimal","value":"."},{"type":"fraction","value":"211"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"432"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}],
+ ],
+ [
+ -Infinity,
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ ],
+ [
+ Infinity,
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"infinity","value":"∞"}],
+ ],
+ [
+ NaN,
+ [{"type":"nan","value":"NaN"}],
+ [{"type":"nan","value":"NaN"}],
+ ],
+];
+
+for (const [number, engineering, scientific] of tests) {
+ const nfEngineering = (new Intl.NumberFormat("ja-JP", { notation: "engineering" }));
+ verifyFormatParts(nfEngineering.formatToParts(number), engineering, `${number} - engineering`);
+ const nfScientific = (new Intl.NumberFormat("ja-JP", { notation: "scientific" }));
+ verifyFormatParts(nfScientific.formatToParts(number), scientific, `${number} - scientific`);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-ko-KR.js
new file mode 100644
index 0000000000..fa6cc8b5c9
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-ko-KR.js
@@ -0,0 +1,88 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the engineering and scientific notations.
+locale: [ko-KR]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ 0.000345,
+ [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"6"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"4"}],
+ ],
+ [
+ 0.345,
+ [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"1"}],
+ ],
+ [
+ 3.45,
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ ],
+ [
+ 34.5,
+ [{"type":"integer","value":"34"},{"type":"decimal","value":"."},{"type":"fraction","value":"5"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"1"}],
+ ],
+ [
+ 543,
+ [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"2"}],
+ ],
+ [
+ 5430,
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ ],
+ [
+ 543000,
+ [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}],
+ ],
+ [
+ 543211.1,
+ [{"type":"integer","value":"543"},{"type":"decimal","value":"."},{"type":"fraction","value":"211"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"432"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}],
+ ],
+ [
+ -Infinity,
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ ],
+ [
+ Infinity,
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"infinity","value":"∞"}],
+ ],
+ [
+ NaN,
+ [{"type":"nan","value":"NaN"}],
+ [{"type":"nan","value":"NaN"}],
+ ],
+];
+
+for (const [number, engineering, scientific] of tests) {
+ const nfEngineering = (new Intl.NumberFormat("ko-KR", { notation: "engineering" }));
+ verifyFormatParts(nfEngineering.formatToParts(number), engineering, `${number} - engineering`);
+ const nfScientific = (new Intl.NumberFormat("ko-KR", { notation: "scientific" }));
+ verifyFormatParts(nfScientific.formatToParts(number), scientific, `${number} - scientific`);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-zh-TW.js
new file mode 100644
index 0000000000..86b59171cc
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-zh-TW.js
@@ -0,0 +1,88 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the engineering and scientific notations.
+locale: [zh-TW]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ 0.000345,
+ [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"6"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"4"}],
+ ],
+ [
+ 0.345,
+ [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"1"}],
+ ],
+ [
+ 3.45,
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ ],
+ [
+ 34.5,
+ [{"type":"integer","value":"34"},{"type":"decimal","value":"."},{"type":"fraction","value":"5"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"1"}],
+ ],
+ [
+ 543,
+ [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"2"}],
+ ],
+ [
+ 5430,
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ ],
+ [
+ 543000,
+ [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}],
+ ],
+ [
+ 543211.1,
+ [{"type":"integer","value":"543"},{"type":"decimal","value":"."},{"type":"fraction","value":"211"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}],
+ [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"432"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}],
+ ],
+ [
+ -Infinity,
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ ],
+ [
+ Infinity,
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"infinity","value":"∞"}],
+ ],
+ [
+ NaN,
+ [{"type":"nan","value":"非數值"}],
+ [{"type":"nan","value":"非數值"}],
+ ],
+];
+
+for (const [number, engineering, scientific] of tests) {
+ const nfEngineering = (new Intl.NumberFormat("zh-TW", { notation: "engineering" }));
+ verifyFormatParts(nfEngineering.formatToParts(number), engineering, `${number} - engineering`);
+ const nfScientific = (new Intl.NumberFormat("zh-TW", { notation: "scientific" }));
+ verifyFormatParts(nfScientific.formatToParts(number), scientific, `${number} - scientific`);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/length.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/length.js
new file mode 100644
index 0000000000..b21012bb80
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/length.js
@@ -0,0 +1,16 @@
+// Copyright 2016 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+description: Intl.NumberFormat.prototype.formatToParts.length.
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Intl.NumberFormat.prototype.formatToParts, "length", {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/main.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/main.js
new file mode 100644
index 0000000000..d6ce6de200
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/main.js
@@ -0,0 +1,67 @@
+// Copyright 2016 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+description: Tests for existance and behavior of Intl.NumberFormat.prototype.formatToParts
+---*/
+
+function reduce(parts) {
+ return parts.map(part => part.value).join('');
+}
+
+function compareFTPtoFormat(locales, options, value) {
+ const nf = new Intl.NumberFormat(locales, options);
+ assert.sameValue(
+ nf.format(value),
+ reduce(nf.formatToParts(value)),
+ `Expected the same value for value ${value},
+ locales: ${locales} and options: ${options}`
+ );
+}
+
+const num1 = 123456.789;
+const num2 = 0.123;
+
+compareFTPtoFormat();
+compareFTPtoFormat('pl');
+compareFTPtoFormat(['pl']);
+compareFTPtoFormat([]);
+compareFTPtoFormat(['de'], undefined, 0);
+compareFTPtoFormat(['de'], undefined, -10);
+compareFTPtoFormat(['de'], undefined, 25324234235);
+compareFTPtoFormat(['de'], undefined, num1);
+compareFTPtoFormat(['de'], {
+ style: 'percent'
+}, num2);
+compareFTPtoFormat(['de'], {
+ style: 'currency',
+ currency: 'EUR'
+}, num1);
+compareFTPtoFormat(['de'], {
+ style: 'currency',
+ currency: 'EUR',
+ currencyDisplay: 'code'
+}, num1);
+compareFTPtoFormat(['de'], {
+ useGrouping: true
+}, num1);
+compareFTPtoFormat(['de'], {
+ useGrouping: false
+}, num1);
+compareFTPtoFormat(['de'], {
+ minimumIntegerDigits: 2
+}, num2);
+compareFTPtoFormat(['de'], {
+ minimumFractionDigits: 6
+}, num2);
+compareFTPtoFormat(['de'], {
+ maximumFractionDigits: 1
+}, num2);
+compareFTPtoFormat(['de'], {
+ maximumSignificantDigits: 3
+}, num1);
+compareFTPtoFormat(['de'], {
+ maximumSignificantDigits: 5
+}, num1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/name.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/name.js
new file mode 100644
index 0000000000..dcfd9b5cec
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/name.js
@@ -0,0 +1,16 @@
+// Copyright 2016 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+description: Intl.NumberFormat.prototype.formatToParts.name value and descriptor.
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Intl.NumberFormat.prototype.formatToParts, "name", {
+ value: "formatToParts",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-de-DE.js
new file mode 100644
index 0000000000..a5de211642
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-de-DE.js
@@ -0,0 +1,94 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the compactDisplay option to the NumberFormat constructor.
+locale: [de-DE]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+const tests = [
+ [
+ 987654321,
+ [{"type":"integer","value":"988"},{"type":"literal","value":"\u00a0"},{"type":"compact","value":"Mio."}],
+ [{"type":"integer","value":"988"},{"type":"literal","value":" "},{"type":"compact","value":"Millionen"}],
+ ],
+ [
+ 98765432,
+ [{"type":"integer","value":"99"},{"type":"literal","value":"\u00a0"},{"type":"compact","value":"Mio."}],
+ [{"type":"integer","value":"99"},{"type":"literal","value":" "},{"type":"compact","value":"Millionen"}],
+ ],
+ [
+ 98765,
+ [{"type":"integer","value":"98"},{"type":"group","value":"."},{"type":"integer","value":"765"}],
+ [{"type":"integer","value":"99"},{"type":"literal","value":" "},{"type":"compact","value":"Tausend"}],
+ ],
+ [
+ 9876,
+ [{"type":"integer","value":"9876"}],
+ [{"type":"integer","value":"9"},{"type":"decimal","value":","},{"type":"fraction","value":"9"},{"type":"literal","value":" "},{"type":"compact","value":"Tausend"}],
+ ],
+ [
+ 159,
+ [{"type":"integer","value":"159"}],
+ ],
+ [
+ 15.9,
+ [{"type":"integer","value":"16"}],
+ ],
+ [
+ 1.59,
+ [{"type":"integer","value":"1"},{"type":"decimal","value":","},{"type":"fraction","value":"6"}],
+ ],
+ [
+ 0.159,
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"16"}],
+ ],
+ [
+ 0.0159,
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"016"}],
+ ],
+ [
+ 0.00159,
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"0016"}],
+ ],
+ [
+ -Infinity,
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ ],
+ [
+ Infinity,
+ [{"type":"infinity","value":"∞"}],
+ ],
+ [
+ NaN,
+ [{"type":"nan","value":"NaN"}],
+ ],
+];
+
+for (const [number, short, long = short] of tests) {
+ const nfShort = new Intl.NumberFormat("de-DE", {
+ notation: "compact",
+ compactDisplay: "short",
+ });
+ verifyFormatParts(nfShort.formatToParts(number), short, `Compact short: ${number}`);
+
+ const nfLong = new Intl.NumberFormat("de-DE", {
+ notation: "compact",
+ compactDisplay: "long",
+ });
+ verifyFormatParts(nfLong.formatToParts(number), long, `Compact long: ${number}`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-en-US.js
new file mode 100644
index 0000000000..84ea596f29
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-en-US.js
@@ -0,0 +1,94 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the compactDisplay option to the NumberFormat constructor.
+locale: [en-US]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+const tests = [
+ [
+ 987654321,
+ [{"type":"integer","value":"988"},{"type":"compact","value":"M"}],
+ [{"type":"integer","value":"988"},{"type":"literal","value":" "},{"type":"compact","value":"million"}],
+ ],
+ [
+ 98765432,
+ [{"type":"integer","value":"99"},{"type":"compact","value":"M"}],
+ [{"type":"integer","value":"99"},{"type":"literal","value":" "},{"type":"compact","value":"million"}],
+ ],
+ [
+ 98765,
+ [{"type":"integer","value":"99"},{"type":"compact","value":"K"}],
+ [{"type":"integer","value":"99"},{"type":"literal","value":" "},{"type":"compact","value":"thousand"}],
+ ],
+ [
+ 9876,
+ [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"compact","value":"K"}],
+ [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"literal","value":" "},{"type":"compact","value":"thousand"}],
+ ],
+ [
+ 159,
+ [{"type":"integer","value":"159"}],
+ ],
+ [
+ 15.9,
+ [{"type":"integer","value":"16"}],
+ ],
+ [
+ 1.59,
+ [{"type":"integer","value":"1"},{"type":"decimal","value":"."},{"type":"fraction","value":"6"}],
+ ],
+ [
+ 0.159,
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"16"}],
+ ],
+ [
+ 0.0159,
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"016"}],
+ ],
+ [
+ 0.00159,
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"0016"}],
+ ],
+ [
+ -Infinity,
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ ],
+ [
+ Infinity,
+ [{"type":"infinity","value":"∞"}],
+ ],
+ [
+ NaN,
+ [{"type":"nan","value":"NaN"}],
+ ],
+];
+
+for (const [number, short, long = short] of tests) {
+ const nfShort = new Intl.NumberFormat("en-US", {
+ notation: "compact",
+ compactDisplay: "short",
+ });
+ verifyFormatParts(nfShort.formatToParts(number), short, `Compact short: ${number}`);
+
+ const nfLong = new Intl.NumberFormat("en-US", {
+ notation: "compact",
+ compactDisplay: "long",
+ });
+ verifyFormatParts(nfLong.formatToParts(number), long, `Compact long: ${number}`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-ja-JP.js
new file mode 100644
index 0000000000..9299f9f7bc
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-ja-JP.js
@@ -0,0 +1,90 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the compactDisplay option to the NumberFormat constructor.
+locale: [ja-JP]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+const tests = [
+ [
+ 987654321,
+ [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"compact","value":"億"}],
+ ],
+ [
+ 98765432,
+ [{"type":"integer","value":"9877"},{"type":"compact","value":"万"}],
+ ],
+ [
+ 98765,
+ [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"compact","value":"万"}],
+ ],
+ [
+ 9876,
+ [{"type":"integer","value":"9876"}],
+ ],
+ [
+ 159,
+ [{"type":"integer","value":"159"}],
+ ],
+ [
+ 15.9,
+ [{"type":"integer","value":"16"}],
+ ],
+ [
+ 1.59,
+ [{"type":"integer","value":"1"},{"type":"decimal","value":"."},{"type":"fraction","value":"6"}],
+ ],
+ [
+ 0.159,
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"16"}],
+ ],
+ [
+ 0.0159,
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"016"}],
+ ],
+ [
+ 0.00159,
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"0016"}],
+ ],
+ [
+ -Infinity,
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ ],
+ [
+ Infinity,
+ [{"type":"infinity","value":"∞"}],
+ ],
+ [
+ NaN,
+ [{"type":"nan","value":"NaN"}],
+ ],
+];
+
+for (const [number, short, long = short] of tests) {
+ const nfShort = new Intl.NumberFormat("ja-JP", {
+ notation: "compact",
+ compactDisplay: "short",
+ });
+ verifyFormatParts(nfShort.formatToParts(number), short, `Compact short: ${number}`);
+
+ const nfLong = new Intl.NumberFormat("ja-JP", {
+ notation: "compact",
+ compactDisplay: "long",
+ });
+ verifyFormatParts(nfLong.formatToParts(number), long, `Compact long: ${number}`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-ko-KR.js
new file mode 100644
index 0000000000..067c9a3b32
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-ko-KR.js
@@ -0,0 +1,90 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the compactDisplay option to the NumberFormat constructor.
+locale: [ko-KR]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+const tests = [
+ [
+ 987654321,
+ [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"compact","value":"억"}],
+ ],
+ [
+ 98765432,
+ [{"type":"integer","value":"9877"},{"type":"compact","value":"만"}],
+ ],
+ [
+ 98765,
+ [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"compact","value":"만"}],
+ ],
+ [
+ 9876,
+ [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"compact","value":"천"}],
+ ],
+ [
+ 159,
+ [{"type":"integer","value":"159"}],
+ ],
+ [
+ 15.9,
+ [{"type":"integer","value":"16"}],
+ ],
+ [
+ 1.59,
+ [{"type":"integer","value":"1"},{"type":"decimal","value":"."},{"type":"fraction","value":"6"}],
+ ],
+ [
+ 0.159,
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"16"}],
+ ],
+ [
+ 0.0159,
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"016"}],
+ ],
+ [
+ 0.00159,
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"0016"}],
+ ],
+ [
+ -Infinity,
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ ],
+ [
+ Infinity,
+ [{"type":"infinity","value":"∞"}],
+ ],
+ [
+ NaN,
+ [{"type":"nan","value":"NaN"}],
+ ],
+];
+
+for (const [number, short, long = short] of tests) {
+ const nfShort = new Intl.NumberFormat("ko-KR", {
+ notation: "compact",
+ compactDisplay: "short",
+ });
+ verifyFormatParts(nfShort.formatToParts(number), short, `Compact short: ${number}`);
+
+ const nfLong = new Intl.NumberFormat("ko-KR", {
+ notation: "compact",
+ compactDisplay: "long",
+ });
+ verifyFormatParts(nfLong.formatToParts(number), long, `Compact long: ${number}`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-zh-TW.js
new file mode 100644
index 0000000000..0b0ab99b1a
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-zh-TW.js
@@ -0,0 +1,90 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the compactDisplay option to the NumberFormat constructor.
+locale: [zh-TW]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+const tests = [
+ [
+ 987654321,
+ [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"compact","value":"億"}],
+ ],
+ [
+ 98765432,
+ [{"type":"integer","value":"9877"},{"type":"compact","value":"萬"}],
+ ],
+ [
+ 98765,
+ [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"compact","value":"萬"}],
+ ],
+ [
+ 9876,
+ [{"type":"integer","value":"9876"}],
+ ],
+ [
+ 159,
+ [{"type":"integer","value":"159"}],
+ ],
+ [
+ 15.9,
+ [{"type":"integer","value":"16"}],
+ ],
+ [
+ 1.59,
+ [{"type":"integer","value":"1"},{"type":"decimal","value":"."},{"type":"fraction","value":"6"}],
+ ],
+ [
+ 0.159,
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"16"}],
+ ],
+ [
+ 0.0159,
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"016"}],
+ ],
+ [
+ 0.00159,
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"0016"}],
+ ],
+ [
+ -Infinity,
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ ],
+ [
+ Infinity,
+ [{"type":"infinity","value":"∞"}],
+ ],
+ [
+ NaN,
+ [{"type":"nan","value":"非數值"}],
+ ],
+];
+
+for (const [number, short, long = short] of tests) {
+ const nfShort = new Intl.NumberFormat("zh-TW", {
+ notation: "compact",
+ compactDisplay: "short",
+ });
+ verifyFormatParts(nfShort.formatToParts(number), short, `Compact short: ${number}`);
+
+ const nfLong = new Intl.NumberFormat("zh-TW", {
+ notation: "compact",
+ compactDisplay: "long",
+ });
+ verifyFormatParts(nfLong.formatToParts(number), long, `Compact long: ${number}`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/percent-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/percent-en-US.js
new file mode 100644
index 0000000000..02b1cb5c42
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/percent-en-US.js
@@ -0,0 +1,38 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the percent style and unit.
+locale: [en-US]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const nfStyle = new Intl.NumberFormat("en-US", { style: "percent" });
+verifyFormatParts(nfStyle.formatToParts(-123), [
+ {"type":"minusSign","value":"-"},
+ {"type":"integer","value":"12"},
+ {"type":"group","value":","},
+ {"type":"integer","value":"300"},
+ {"type":"percentSign","value":"%"},
+], "style");
+
+const nfUnit = new Intl.NumberFormat("en-US", { style: "unit", unit: "percent" });
+verifyFormatParts(nfUnit.formatToParts(-123), [
+ {"type":"minusSign","value":"-"},
+ {"type":"integer","value":"123"},
+ {"type":"unit","value":"%"},
+], "unit");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/prop-desc.js
new file mode 100644
index 0000000000..e667e3bb32
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/prop-desc.js
@@ -0,0 +1,41 @@
+// Copyright 2016 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: >
+ "formatToParts" property of Intl.NumberFormat.prototype.
+info: |
+ 11.4.4 Intl.NumberFormat.prototype.formatToParts
+
+ 7 Requirements for Standard Built-in ECMAScript Objects
+
+ Unless specified otherwise in this document, the objects, functions, and constructors
+ described in this standard are subject to the generic requirements and restrictions
+ specified for standard built-in ECMAScript objects in the ECMAScript 2018 Language
+ Specification, 9th edition, clause 17, or successor.
+
+ 17 ECMAScript Standard Built-in Objects:
+
+ Every accessor property described in clauses 18 through 26 and in Annex B.2 has the
+ attributes { [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified.
+ If only a get accessor function is described, the set accessor function is the default
+ value, undefined. If only a set accessor is described the get accessor is the default
+ value, undefined.
+
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(
+ typeof Intl.NumberFormat.prototype.formatToParts,
+ 'function',
+ '`typeof Intl.NumberFormat.prototype.formatToParts` is `function`'
+);
+
+verifyProperty(Intl.NumberFormat.prototype, "formatToParts", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/shell.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/shell.js
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-de-DE.js
new file mode 100644
index 0000000000..d2f61becd6
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-de-DE.js
@@ -0,0 +1,72 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [de-DE]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ "auto",
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ ],
+ [
+ "always",
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ ],
+ [
+ "never",
+ [{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ ],
+ [
+ "exceptZero",
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ ],
+];
+
+for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) {
+ const nf = new Intl.NumberFormat("de-DE", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay });
+ verifyFormatParts(nf.formatToParts(-987), negative, "negative");
+ verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero, "negativeNearZero");
+ verifyFormatParts(nf.formatToParts(-0), negativeZero, "negativeZero");
+ verifyFormatParts(nf.formatToParts(0), zero, "zero");
+ verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero, "positiveNearZero");
+ verifyFormatParts(nf.formatToParts(987), positive, "positive");
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-en-US.js
new file mode 100644
index 0000000000..9905591d77
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-en-US.js
@@ -0,0 +1,72 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [en-US]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ "auto",
+ [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ ],
+ [
+ "always",
+ [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"plusSign","value":"+"},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"plusSign","value":"+"},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"plusSign","value":"+"},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ ],
+ [
+ "never",
+ [{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ ],
+ [
+ "exceptZero",
+ [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"plusSign","value":"+"},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ ],
+];
+
+for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) {
+ const nf = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay });
+ verifyFormatParts(nf.formatToParts(-987), negative, "negative");
+ verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero, "negativeNearZero");
+ verifyFormatParts(nf.formatToParts(-0), negativeZero, "negativeZero");
+ verifyFormatParts(nf.formatToParts(0), zero, "zero");
+ verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero, "positiveNearZero");
+ verifyFormatParts(nf.formatToParts(987), positive, "positive");
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ja-JP.js
new file mode 100644
index 0000000000..67d4db79b3
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ja-JP.js
@@ -0,0 +1,72 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [ja-JP]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ "auto",
+ [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ ],
+ [
+ "always",
+ [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"plusSign","value":"+"},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"plusSign","value":"+"},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"plusSign","value":"+"},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ ],
+ [
+ "never",
+ [{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ ],
+ [
+ "exceptZero",
+ [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"plusSign","value":"+"},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ ],
+];
+
+for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) {
+ const nf = new Intl.NumberFormat("ja-JP", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay });
+ verifyFormatParts(nf.formatToParts(-987), negative, "negative");
+ verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero, "negativeNearZero");
+ verifyFormatParts(nf.formatToParts(-0), negativeZero, "negativeZero");
+ verifyFormatParts(nf.formatToParts(0), zero, "zero");
+ verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero, "positiveNearZero");
+ verifyFormatParts(nf.formatToParts(987), positive, "positive");
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ko-KR.js
new file mode 100644
index 0000000000..226394e2ef
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ko-KR.js
@@ -0,0 +1,72 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [ko-KR]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ "auto",
+ [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ ],
+ [
+ "always",
+ [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"plusSign","value":"+"},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"plusSign","value":"+"},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"plusSign","value":"+"},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ ],
+ [
+ "never",
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ ],
+ [
+ "exceptZero",
+ [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"plusSign","value":"+"},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ ],
+];
+
+for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) {
+ const nf = new Intl.NumberFormat("ko-KR", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay });
+ verifyFormatParts(nf.formatToParts(-987), negative, "negative");
+ verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero, "negativeNearZero");
+ verifyFormatParts(nf.formatToParts(-0), negativeZero, "negativeZero");
+ verifyFormatParts(nf.formatToParts(0), zero, "zero");
+ verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero, "positiveNearZero");
+ verifyFormatParts(nf.formatToParts(987), positive, "positive");
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-zh-TW.js
new file mode 100644
index 0000000000..27027aee33
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-zh-TW.js
@@ -0,0 +1,72 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [zh-TW]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ "auto",
+ [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ ],
+ [
+ "always",
+ [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"plusSign","value":"+"},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"plusSign","value":"+"},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"plusSign","value":"+"},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ ],
+ [
+ "never",
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ ],
+ [
+ "exceptZero",
+ [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ [{"type":"plusSign","value":"+"},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ ],
+];
+
+for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) {
+ const nf = new Intl.NumberFormat("zh-TW", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay });
+ verifyFormatParts(nf.formatToParts(-987), negative, "negative");
+ verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero, "negativeNearZero");
+ verifyFormatParts(nf.formatToParts(-0), negativeZero, "negativeZero");
+ verifyFormatParts(nf.formatToParts(0), zero, "zero");
+ verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero, "positiveNearZero");
+ verifyFormatParts(nf.formatToParts(987), positive, "positive");
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-de-DE.js
new file mode 100644
index 0000000000..f0e57379f6
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-de-DE.js
@@ -0,0 +1,87 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [de-DE]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ "auto",
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"987"}],
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"nan","value":"NaN"}],
+ ],
+ [
+ "always",
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}],
+ [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}],
+ [{"type":"plusSign","value":"+"},{"type":"nan","value":"NaN"}],
+ ],
+ [
+ "never",
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"integer","value":"987"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"987"}],
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"nan","value":"NaN"}],
+ ],
+ [
+ "exceptZero",
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}],
+ [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}],
+ [{"type":"nan","value":"NaN"}],
+ ],
+];
+
+for (const [signDisplay, ...expected] of tests) {
+ const nf = new Intl.NumberFormat("de-DE", {signDisplay});
+ verifyFormatParts(nf.formatToParts(-Infinity), expected[0], `-Infinity (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(-987), expected[1], `-987 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(-0.0001), expected[2], `-0.0001 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(-0), expected[3], `-0 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(0), expected[4], `0 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(0.0001), expected[5], `0.0001 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(987), expected[6], `987 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(Infinity), expected[7], `Infinity (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(NaN), expected[8], `NaN (${signDisplay})`);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-en-US.js
new file mode 100644
index 0000000000..6fdf3bb5a1
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-en-US.js
@@ -0,0 +1,87 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [en-US]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ "auto",
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"987"}],
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"nan","value":"NaN"}],
+ ],
+ [
+ "always",
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}],
+ [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}],
+ [{"type":"plusSign","value":"+"},{"type":"nan","value":"NaN"}],
+ ],
+ [
+ "never",
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"integer","value":"987"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"987"}],
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"nan","value":"NaN"}],
+ ],
+ [
+ "exceptZero",
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}],
+ [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}],
+ [{"type":"nan","value":"NaN"}],
+ ],
+];
+
+for (const [signDisplay, ...expected] of tests) {
+ const nf = new Intl.NumberFormat("en-US", {signDisplay});
+ verifyFormatParts(nf.formatToParts(-Infinity), expected[0], `-Infinity (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(-987), expected[1], `-987 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(-0.0001), expected[2], `-0.0001 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(-0), expected[3], `-0 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(0), expected[4], `0 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(0.0001), expected[5], `0.0001 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(987), expected[6], `987 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(Infinity), expected[7], `Infinity (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(NaN), expected[8], `NaN (${signDisplay})`);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-ja-JP.js
new file mode 100644
index 0000000000..41748c1dab
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-ja-JP.js
@@ -0,0 +1,87 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [ja-JP]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ "auto",
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"987"}],
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"nan","value":"NaN"}],
+ ],
+ [
+ "always",
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}],
+ [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}],
+ [{"type":"plusSign","value":"+"},{"type":"nan","value":"NaN"}],
+ ],
+ [
+ "never",
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"integer","value":"987"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"987"}],
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"nan","value":"NaN"}],
+ ],
+ [
+ "exceptZero",
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}],
+ [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}],
+ [{"type":"nan","value":"NaN"}],
+ ],
+];
+
+for (const [signDisplay, ...expected] of tests) {
+ const nf = new Intl.NumberFormat("ja-JP", {signDisplay});
+ verifyFormatParts(nf.formatToParts(-Infinity), expected[0], `-Infinity (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(-987), expected[1], `-987 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(-0.0001), expected[2], `-0.0001 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(-0), expected[3], `-0 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(0), expected[4], `0 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(0.0001), expected[5], `0.0001 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(987), expected[6], `987 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(Infinity), expected[7], `Infinity (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(NaN), expected[8], `NaN (${signDisplay})`);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-ko-KR.js
new file mode 100644
index 0000000000..6a751269f3
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-ko-KR.js
@@ -0,0 +1,87 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [ko-KR]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ "auto",
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"987"}],
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"nan","value":"NaN"}],
+ ],
+ [
+ "always",
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}],
+ [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}],
+ [{"type":"plusSign","value":"+"},{"type":"nan","value":"NaN"}],
+ ],
+ [
+ "never",
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"integer","value":"987"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"987"}],
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"nan","value":"NaN"}],
+ ],
+ [
+ "exceptZero",
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}],
+ [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}],
+ [{"type":"nan","value":"NaN"}],
+ ],
+];
+
+for (const [signDisplay, ...expected] of tests) {
+ const nf = new Intl.NumberFormat("ko-KR", {signDisplay});
+ verifyFormatParts(nf.formatToParts(-Infinity), expected[0], `-Infinity (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(-987), expected[1], `-987 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(-0.0001), expected[2], `-0.0001 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(-0), expected[3], `-0 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(0), expected[4], `0 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(0.0001), expected[5], `0.0001 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(987), expected[6], `987 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(Infinity), expected[7], `Infinity (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(NaN), expected[8], `NaN (${signDisplay})`);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-de-DE.js
new file mode 100644
index 0000000000..f3ef8fb416
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-de-DE.js
@@ -0,0 +1,55 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [de-DE]
+features: [Intl.NumberFormat-v3]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const nf = new Intl.NumberFormat("de-DE", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" });
+
+verifyFormatParts(
+ nf.formatToParts(-987),
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ "negative"
+);
+verifyFormatParts(
+ nf.formatToParts(-0.0001),
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ "negativeNearZero"
+);
+verifyFormatParts(
+ nf.formatToParts(-0),
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ "negativeZero"
+);
+verifyFormatParts(
+ nf.formatToParts(0),
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ "zero"
+);
+verifyFormatParts(
+ nf.formatToParts(0.0001),
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ "positiveNearZero"
+);
+verifyFormatParts(
+ nf.formatToParts(987),
+ [{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}],
+ "positive"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-en-US.js
new file mode 100644
index 0000000000..09b9e26d0f
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-en-US.js
@@ -0,0 +1,55 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [en-US]
+features: [Intl.NumberFormat-v3]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const nf = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" });
+
+verifyFormatParts(
+ nf.formatToParts(-987),
+ [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ "negative"
+);
+verifyFormatParts(
+ nf.formatToParts(-0.0001),
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "negativeNearZero"
+);
+verifyFormatParts(
+ nf.formatToParts(-0),
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "negativeZero"
+);
+verifyFormatParts(
+ nf.formatToParts(0),
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "zero"
+);
+verifyFormatParts(
+ nf.formatToParts(0.0001),
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "positiveNearZero"
+);
+verifyFormatParts(
+ nf.formatToParts(987),
+ [{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "positive"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-ja-JP.js
new file mode 100644
index 0000000000..a651563b23
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-ja-JP.js
@@ -0,0 +1,55 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [ja-JP]
+features: [Intl.NumberFormat-v3]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const nf = new Intl.NumberFormat("ja-JP", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" });
+
+verifyFormatParts(
+ nf.formatToParts(-987),
+ [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ "negative"
+);
+verifyFormatParts(
+ nf.formatToParts(-0.0001),
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "negativeNearZero"
+);
+verifyFormatParts(
+ nf.formatToParts(-0),
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "negativeZero"
+);
+verifyFormatParts(
+ nf.formatToParts(0),
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "zero"
+);
+verifyFormatParts(
+ nf.formatToParts(0.0001),
+ [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "positiveNearZero"
+);
+verifyFormatParts(
+ nf.formatToParts(987),
+ [{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "positive"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-ko-KR.js
new file mode 100644
index 0000000000..c7263383b7
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-ko-KR.js
@@ -0,0 +1,55 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [ko-KR]
+features: [Intl.NumberFormat-v3]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const nf = new Intl.NumberFormat("ko-KR", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" });
+
+verifyFormatParts(
+ nf.formatToParts(-987),
+ [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ "negative"
+);
+verifyFormatParts(
+ nf.formatToParts(-0.0001),
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "negativeNearZero"
+);
+verifyFormatParts(
+ nf.formatToParts(-0),
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "negativeZero"
+);
+verifyFormatParts(
+ nf.formatToParts(0),
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "zero"
+);
+verifyFormatParts(
+ nf.formatToParts(0.0001),
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "positiveNearZero"
+);
+verifyFormatParts(
+ nf.formatToParts(987),
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "positive"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-zh-TW.js
new file mode 100644
index 0000000000..aa2ca4a810
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-currency-zh-TW.js
@@ -0,0 +1,55 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [zh-TW]
+features: [Intl.NumberFormat-v3]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const nf = new Intl.NumberFormat("zh-TW", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay: "negative" });
+
+verifyFormatParts(
+ nf.formatToParts(-987),
+ [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}],
+ "negative"
+);
+verifyFormatParts(
+ nf.formatToParts(-0.0001),
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "negativeNearZero"
+);
+verifyFormatParts(
+ nf.formatToParts(-0),
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "negativeZero"
+);
+verifyFormatParts(
+ nf.formatToParts(0),
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "zero"
+);
+verifyFormatParts(
+ nf.formatToParts(0.0001),
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "positiveNearZero"
+);
+verifyFormatParts(
+ nf.formatToParts(987),
+ [{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}],
+ "positive"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-de-DE.js
new file mode 100644
index 0000000000..ea25559606
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-de-DE.js
@@ -0,0 +1,35 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [de-DE]
+features: [Intl.NumberFormat-v3]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const signDisplay = "negative";
+const nf = new Intl.NumberFormat("de-DE", {signDisplay: "negative"});
+
+verifyFormatParts(nf.formatToParts(-Infinity), [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], `-Infinity (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(-987), [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], `-987 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(-0.0001), [{"type":"integer","value":"0"}], `-0.0001 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(-0), [{"type":"integer","value":"0"}], `-0 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(0), [{"type":"integer","value":"0"}], `0 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(0.0001), [{"type":"integer","value":"0"}], `0.0001 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(987), [{"type":"integer","value":"987"}], `987 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(Infinity), [{"type":"infinity","value":"∞"}], `Infinity (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(NaN), [{"type":"nan","value":"NaN"}], `NaN (${signDisplay})`);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-en-US.js
new file mode 100644
index 0000000000..07b2bee627
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-en-US.js
@@ -0,0 +1,35 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [en-US]
+features: [Intl.NumberFormat-v3]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const signDisplay = "negative";
+const nf = new Intl.NumberFormat("en-US", {signDisplay: "negative"});
+
+verifyFormatParts(nf.formatToParts(-Infinity), [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], `-Infinity (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(-987), [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], `-987 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(-0.0001), [{"type":"integer","value":"0"}], `-0.0001 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(-0), [{"type":"integer","value":"0"}], `-0 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(0), [{"type":"integer","value":"0"}], `0 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(0.0001), [{"type":"integer","value":"0"}], `0.0001 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(987), [{"type":"integer","value":"987"}], `987 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(Infinity), [{"type":"infinity","value":"∞"}], `Infinity (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(NaN), [{"type":"nan","value":"NaN"}], `NaN (${signDisplay})`);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-ja-JP.js
new file mode 100644
index 0000000000..fe9da55796
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-ja-JP.js
@@ -0,0 +1,35 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [ja-JP]
+features: [Intl.NumberFormat-v3]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const signDisplay = "negative";
+const nf = new Intl.NumberFormat("ja-JP", {signDisplay: "negative"});
+
+verifyFormatParts(nf.formatToParts(-Infinity), [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], `-Infinity (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(-987), [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], `-987 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(-0.0001), [{"type":"integer","value":"0"}], `-0.0001 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(-0), [{"type":"integer","value":"0"}], `-0 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(0), [{"type":"integer","value":"0"}], `0 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(0.0001), [{"type":"integer","value":"0"}], `0.0001 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(987), [{"type":"integer","value":"987"}], `987 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(Infinity), [{"type":"infinity","value":"∞"}], `Infinity (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(NaN), [{"type":"nan","value":"NaN"}], `NaN (${signDisplay})`);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-ko-KR.js
new file mode 100644
index 0000000000..faa534d236
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-ko-KR.js
@@ -0,0 +1,35 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [ko-KR]
+features: [Intl.NumberFormat-v3]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const signDisplay = "negative";
+const nf = new Intl.NumberFormat("ko-KR", {signDisplay: "negative"});
+
+verifyFormatParts(nf.formatToParts(-Infinity), [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], `-Infinity (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(-987), [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], `-987 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(-0.0001), [{"type":"integer","value":"0"}], `-0.0001 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(-0), [{"type":"integer","value":"0"}], `-0 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(0), [{"type":"integer","value":"0"}], `0 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(0.0001), [{"type":"integer","value":"0"}], `0.0001 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(987), [{"type":"integer","value":"987"}], `987 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(Infinity), [{"type":"infinity","value":"∞"}], `Infinity (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(NaN), [{"type":"nan","value":"NaN"}], `NaN (${signDisplay})`);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-zh-TW.js
new file mode 100644
index 0000000000..902fa281c1
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-negative-zh-TW.js
@@ -0,0 +1,35 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [zh-TW]
+features: [Intl.NumberFormat-v3]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const signDisplay = "negative";
+const nf = new Intl.NumberFormat("zh-TW", {signDisplay: "negative"});
+
+verifyFormatParts(nf.formatToParts(-Infinity), [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], `-Infinity (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(-987), [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], `-987 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(-0.0001), [{"type":"integer","value":"0"}], `-0.0001 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(-0), [{"type":"integer","value":"0"}], `-0 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(0), [{"type":"integer","value":"0"}], `0 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(0.0001), [{"type":"integer","value":"0"}], `0.0001 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(987), [{"type":"integer","value":"987"}], `987 (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(Infinity), [{"type":"infinity","value":"∞"}], `Infinity (${signDisplay})`);
+verifyFormatParts(nf.formatToParts(NaN), [{"type":"nan","value":"非數值"}], `NaN (${signDisplay})`);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-zh-TW.js
new file mode 100644
index 0000000000..e3d2d30fa1
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-zh-TW.js
@@ -0,0 +1,87 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the signDisplay option to the NumberFormat constructor.
+locale: [zh-TW]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ "auto",
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"987"}],
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"nan","value":"非數值"}],
+ ],
+ [
+ "always",
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}],
+ [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}],
+ [{"type":"plusSign","value":"+"},{"type":"nan","value":"非數值"}],
+ ],
+ [
+ "never",
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"integer","value":"987"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"987"}],
+ [{"type":"infinity","value":"∞"}],
+ [{"type":"nan","value":"非數值"}],
+ ],
+ [
+ "exceptZero",
+ [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}],
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"integer","value":"0"}],
+ [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}],
+ [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}],
+ [{"type":"nan","value":"非數值"}],
+ ],
+];
+
+for (const [signDisplay, ...expected] of tests) {
+ const nf = new Intl.NumberFormat("zh-TW", {signDisplay});
+ verifyFormatParts(nf.formatToParts(-Infinity), expected[0], `-Infinity (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(-987), expected[1], `-987 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(-0.0001), expected[2], `-0.0001 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(-0), expected[3], `-0 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(0), expected[4], `0 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(0.0001), expected[5], `0.0001 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(987), expected[6], `987 (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(Infinity), expected[7], `Infinity (${signDisplay})`);
+ verifyFormatParts(nf.formatToParts(NaN), expected[8], `NaN (${signDisplay})`);
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/this-value-not-numberformat.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/this-value-not-numberformat.js
new file mode 100644
index 0000000000..e5beb30623
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/this-value-not-numberformat.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2018 Ujjwal Sharma. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat.prototype.formatToParts
+description: >
+ Tests that Intl.NumberFormat.prototype.formatToParts throws a
+ TypeError if called on a non-object value or an object that hasn't
+ been initialized as a NumberFormat.
+---*/
+
+const invalidTargets = [undefined, null, true, 0, 'NumberFormat', [], {}, Symbol()];
+const fn = Intl.NumberFormat.prototype.formatToParts;
+
+invalidTargets.forEach(target => {
+ assert.throws(
+ TypeError,
+ () => fn.call(target),
+ `Calling formatToParts on ${String(target)} should throw a TypeError.`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-de-DE.js
new file mode 100644
index 0000000000..ce186e9ecf
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-de-DE.js
@@ -0,0 +1,99 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the unit style.
+locale: [de-DE]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ -987,
+ {
+ "short":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"Kilometer pro Stunde"}],
+ }
+ ],
+ [
+ -0.001,
+ {
+ "short":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"Kilometer pro Stunde"}],
+ }
+ ],
+ [
+ -0,
+ {
+ "short":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"Kilometer pro Stunde"}],
+ }
+ ],
+ [
+ 0,
+ {
+ "short":
+ [{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"Kilometer pro Stunde"}],
+ }
+ ],
+ [
+ 0.001,
+ {
+ "short":
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"Kilometer pro Stunde"}],
+ }
+ ],
+ [
+ 987,
+ {
+ "short":
+ [{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"Kilometer pro Stunde"}],
+ }
+ ],
+];
+
+for (const [number, expectedData] of tests) {
+ for (const [unitDisplay, expected] of Object.entries(expectedData)) {
+ const nf = new Intl.NumberFormat("de-DE", { style: "unit", unit: "kilometer-per-hour", unitDisplay });
+ verifyFormatParts(nf.formatToParts(number), expected);
+ }
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-en-US.js
new file mode 100644
index 0000000000..db2220de22
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-en-US.js
@@ -0,0 +1,99 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the unit style.
+locale: [en-US]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ -987,
+ {
+ "short":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"kilometers per hour"}],
+ }
+ ],
+ [
+ -0.001,
+ {
+ "short":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"kilometers per hour"}],
+ }
+ ],
+ [
+ -0,
+ {
+ "short":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"kilometers per hour"}],
+ }
+ ],
+ [
+ 0,
+ {
+ "short":
+ [{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"integer","value":"0"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"kilometers per hour"}],
+ }
+ ],
+ [
+ 0.001,
+ {
+ "short":
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"kilometers per hour"}],
+ }
+ ],
+ [
+ 987,
+ {
+ "short":
+ [{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"integer","value":"987"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"kilometers per hour"}],
+ }
+ ],
+];
+
+for (const [number, expectedData] of tests) {
+ for (const [unitDisplay, expected] of Object.entries(expectedData)) {
+ const nf = new Intl.NumberFormat("en-US", { style: "unit", unit: "kilometer-per-hour", unitDisplay });
+ verifyFormatParts(nf.formatToParts(number), expected);
+ }
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-ja-JP.js
new file mode 100644
index 0000000000..2296f529a8
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-ja-JP.js
@@ -0,0 +1,99 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the unit style.
+locale: [ja-JP]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ -987,
+ {
+ "short":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"unit","value":"時速"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"キロメートル"}],
+ }
+ ],
+ [
+ -0.001,
+ {
+ "short":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"unit","value":"時速"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"キロメートル"}],
+ }
+ ],
+ [
+ -0,
+ {
+ "short":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"unit","value":"時速"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"キロメートル"}],
+ }
+ ],
+ [
+ 0,
+ {
+ "short":
+ [{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"integer","value":"0"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"unit","value":"時速"},{"type":"literal","value":" "},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"キロメートル"}],
+ }
+ ],
+ [
+ 0.001,
+ {
+ "short":
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"unit","value":"時速"},{"type":"literal","value":" "},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"キロメートル"}],
+ }
+ ],
+ [
+ 987,
+ {
+ "short":
+ [{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"integer","value":"987"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"unit","value":"時速"},{"type":"literal","value":" "},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"キロメートル"}],
+ }
+ ],
+];
+
+for (const [number, expectedData] of tests) {
+ for (const [unitDisplay, expected] of Object.entries(expectedData)) {
+ const nf = new Intl.NumberFormat("ja-JP", { style: "unit", unit: "kilometer-per-hour", unitDisplay });
+ verifyFormatParts(nf.formatToParts(number), expected);
+ }
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-ko-KR.js
new file mode 100644
index 0000000000..74d938b513
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-ko-KR.js
@@ -0,0 +1,99 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the unit style.
+locale: [ko-KR]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ -987,
+ {
+ "short":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"unit","value":"시속"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"unit","value":"킬로미터"}],
+ }
+ ],
+ [
+ -0.001,
+ {
+ "short":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"unit","value":"시속"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"킬로미터"}],
+ }
+ ],
+ [
+ -0,
+ {
+ "short":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"unit","value":"시속"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"unit","value":"킬로미터"}],
+ }
+ ],
+ [
+ 0,
+ {
+ "short":
+ [{"type":"integer","value":"0"},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"integer","value":"0"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"unit","value":"시속"},{"type":"literal","value":" "},{"type":"integer","value":"0"},{"type":"unit","value":"킬로미터"}],
+ }
+ ],
+ [
+ 0.001,
+ {
+ "short":
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"unit","value":"시속"},{"type":"literal","value":" "},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"킬로미터"}],
+ }
+ ],
+ [
+ 987,
+ {
+ "short":
+ [{"type":"integer","value":"987"},{"type":"unit","value":"km/h"}],
+ "narrow":
+ [{"type":"integer","value":"987"},{"type":"unit","value":"km/h"}],
+ "long":
+ [{"type":"unit","value":"시속"},{"type":"literal","value":" "},{"type":"integer","value":"987"},{"type":"unit","value":"킬로미터"}],
+ }
+ ],
+];
+
+for (const [number, expectedData] of tests) {
+ for (const [unitDisplay, expected] of Object.entries(expectedData)) {
+ const nf = new Intl.NumberFormat("ko-KR", { style: "unit", unit: "kilometer-per-hour", unitDisplay });
+ verifyFormatParts(nf.formatToParts(number), expected);
+ }
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-zh-TW.js
new file mode 100644
index 0000000000..6399ff7023
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-zh-TW.js
@@ -0,0 +1,99 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the unit style.
+locale: [zh-TW]
+features: [Intl.NumberFormat-unified]
+---*/
+
+function verifyFormatParts(actual, expected, message) {
+ assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`);
+ assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`);
+ assert.sameValue(actual.length, expected.length, `${message}: length`);
+
+ for (let i = 0; i < actual.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`);
+ assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`);
+ }
+}
+
+const tests = [
+ [
+ -987,
+ {
+ "short":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"公里/小時"}],
+ "narrow":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"unit","value":"公里/小時"}],
+ "long":
+ [{"type":"unit","value":"每小時"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"公里"}],
+ }
+ ],
+ [
+ -0.001,
+ {
+ "short":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"公里/小時"}],
+ "narrow":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"公里/小時"}],
+ "long":
+ [{"type":"unit","value":"每小時"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"公里"}],
+ }
+ ],
+ [
+ -0,
+ {
+ "short":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"公里/小時"}],
+ "narrow":
+ [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"unit","value":"公里/小時"}],
+ "long":
+ [{"type":"unit","value":"每小時"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"公里"}],
+ }
+ ],
+ [
+ 0,
+ {
+ "short":
+ [{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"公里/小時"}],
+ "narrow":
+ [{"type":"integer","value":"0"},{"type":"unit","value":"公里/小時"}],
+ "long":
+ [{"type":"unit","value":"每小時"},{"type":"literal","value":" "},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"公里"}],
+ }
+ ],
+ [
+ 0.001,
+ {
+ "short":
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"公里/小時"}],
+ "narrow":
+ [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"公里/小時"}],
+ "long":
+ [{"type":"unit","value":"每小時"},{"type":"literal","value":" "},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"公里"}],
+ }
+ ],
+ [
+ 987,
+ {
+ "short":
+ [{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"公里/小時"}],
+ "narrow":
+ [{"type":"integer","value":"987"},{"type":"unit","value":"公里/小時"}],
+ "long":
+ [{"type":"unit","value":"每小時"},{"type":"literal","value":" "},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"公里"}],
+ }
+ ],
+];
+
+for (const [number, expectedData] of tests) {
+ for (const [unitDisplay, expected] of Object.entries(expectedData)) {
+ const nf = new Intl.NumberFormat("zh-TW", { style: "unit", unit: "kilometer-per-hour", unitDisplay });
+ verifyFormatParts(nf.formatToParts(number), expected);
+ }
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit.js
new file mode 100644
index 0000000000..54b165ed89
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit.js
@@ -0,0 +1,27 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: Checks handling of the unit style.
+features: [Intl.NumberFormat-unified]
+---*/
+
+const numbers = [-987, -0.001, -0, 0, 0.001, 987];
+const displays = [
+ "short",
+ "narrow",
+ "long",
+];
+
+for (const unitDisplay of displays) {
+ const nf = new Intl.NumberFormat("en-US", { style: "unit", unit: "meter", unitDisplay });
+ for (const number of numbers) {
+ const result = nf.formatToParts(number);
+ assert.sameValue(result.map(({ value }) => value).join(""), nf.format(number));
+ assert.sameValue(result.some(({ type }) => type === "unit"), true);
+ }
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/value-tonumber.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/value-tonumber.js
new file mode 100644
index 0000000000..c2601b026f
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/value-tonumber.js
@@ -0,0 +1,52 @@
+// Copyright 2016 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.formattoparts
+description: >
+ Tests that Intl.NumberFormat.prototype.formatToParts converts
+ its argument (called value) to a number using ToNumber (7.1.3).
+info: |
+ 11.1.4 Number Format Functions
+
+ 4. Let x be ? ToNumber(value).
+features: [Symbol]
+---*/
+
+const toNumberResults = [
+ [undefined, NaN],
+ [null, +0],
+ [true, 1],
+ [false, +0],
+ ['42', 42],
+ ['foo', NaN]
+];
+
+const nf = new Intl.NumberFormat();
+
+function assertSameParts(actual, expected) {
+ assert.sameValue(actual.length, expected.length);
+ for (let i = 0; i < expected.length; ++i) {
+ assert.sameValue(actual[i].type, expected[i].type);
+ assert.sameValue(actual[i].value, expected[i].value);
+ }
+}
+
+toNumberResults.forEach(pair => {
+ const [value, result] = pair;
+ assertSameParts(nf.formatToParts(value), nf.formatToParts(result));
+});
+
+let count = 0;
+const dummy = {};
+dummy[Symbol.toPrimitive] = hint => (hint === 'number' ? ++count : NaN);
+assertSameParts(nf.formatToParts(dummy), nf.formatToParts(count));
+assert.sameValue(count, 1);
+
+assert.throws(
+ TypeError,
+ () => nf.formatToParts(Symbol()),
+ "ToNumber(arg) throws a TypeError when arg is of type 'Symbol'"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/prop-desc.js
new file mode 100644
index 0000000000..24b65adc9a
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/prop-desc.js
@@ -0,0 +1,17 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+es5id: 11.2.1
+description: Tests that Intl.NumberFormat.prototype has the required attributes.
+author: Norbert Lindenberg
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Intl.NumberFormat, "prototype", {
+ writable: false,
+ enumerable: false,
+ configurable: false,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/basic.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/basic.js
new file mode 100644
index 0000000000..ffde22cf3a
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/basic.js
@@ -0,0 +1,45 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// Copyright 2022 Apple Inc. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+es5id: 11.3.3
+description: >
+ Tests that the object returned by
+ Intl.NumberFormat.prototype.resolvedOptions has the right
+ properties.
+author: Norbert Lindenberg
+includes: [testIntl.js, propertyHelper.js]
+features: [Intl.NumberFormat-v3]
+---*/
+
+var actual = new Intl.NumberFormat().resolvedOptions();
+
+var actual2 = new Intl.NumberFormat().resolvedOptions();
+assert.notSameValue(actual2, actual, "resolvedOptions returned the same object twice.");
+
+// this assumes the default values where the specification provides them
+assert(isCanonicalizedStructurallyValidLanguageTag(actual.locale),
+ "Invalid locale: " + actual.locale);
+assert(isValidNumberingSystem(actual.numberingSystem),
+ "Invalid numbering system: " + actual.numberingSystem);
+assert.sameValue(actual.style, "decimal");
+assert.sameValue(actual.minimumIntegerDigits, 1);
+assert.sameValue(actual.minimumFractionDigits, 0);
+assert.sameValue(actual.maximumFractionDigits, 3);
+assert.sameValue(actual.useGrouping, "auto");
+
+var dataPropertyDesc = { writable: true, enumerable: true, configurable: true };
+verifyProperty(actual, "locale", dataPropertyDesc);
+verifyProperty(actual, "numberingSystem", dataPropertyDesc);
+verifyProperty(actual, "style", dataPropertyDesc);
+verifyProperty(actual, "currency", undefined);
+verifyProperty(actual, "currencyDisplay", undefined);
+verifyProperty(actual, "minimumIntegerDigits", dataPropertyDesc);
+verifyProperty(actual, "minimumFractionDigits", dataPropertyDesc);
+verifyProperty(actual, "maximumFractionDigits", dataPropertyDesc);
+verifyProperty(actual, "minimumSignificantDigits", undefined);
+verifyProperty(actual, "maximumSignificantDigits", undefined);
+verifyProperty(actual, "useGrouping", dataPropertyDesc);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/browser.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/browser.js
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/builtin.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/builtin.js
new file mode 100644
index 0000000000..c513cc7fa5
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/builtin.js
@@ -0,0 +1,30 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+es5id: 11.3.3_L15
+description: >
+ Tests that Intl.NumberFormat.prototype.resolvedOptions meets the
+ requirements for built-in objects defined by the introduction of
+ chapter 17 of the ECMAScript Language Specification.
+author: Norbert Lindenberg
+includes: [isConstructor.js]
+features: [Reflect.construct]
+---*/
+
+assert.sameValue(Object.prototype.toString.call(Intl.NumberFormat.prototype.resolvedOptions), "[object Function]",
+ "The [[Class]] internal property of a built-in function must be " +
+ "\"Function\".");
+
+assert(Object.isExtensible(Intl.NumberFormat.prototype.resolvedOptions),
+ "Built-in objects must be extensible.");
+
+assert.sameValue(Object.getPrototypeOf(Intl.NumberFormat.prototype.resolvedOptions), Function.prototype);
+
+assert.sameValue(Intl.NumberFormat.prototype.resolvedOptions.hasOwnProperty("prototype"), false,
+ "Built-in functions that aren't constructors must not have a prototype property.");
+
+assert.sameValue(isConstructor(Intl.NumberFormat.prototype.resolvedOptions), false,
+ "Built-in functions don't implement [[Construct]] unless explicitly specified.");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/compactDisplay.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/compactDisplay.js
new file mode 100644
index 0000000000..9d42cee786
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/compactDisplay.js
@@ -0,0 +1,26 @@
+// Copyright 2019 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.resolvedoptions
+description: Verifies the existence of the compactDisplay property for the object returned by resolvedOptions().
+features: [Intl.NumberFormat-unified]
+---*/
+
+for (const notation of [undefined, "standard", "scientific", "engineering"]) {
+ const options = new Intl.NumberFormat([], {
+ notation,
+ compactDisplay: "long",
+ }).resolvedOptions();
+ assert.sameValue("compactDisplay" in options, false, `There should be no compactDisplay property with notation=${notation}`);
+ assert.sameValue(options.compactDisplay, undefined, `The compactDisplay property should be undefined with notation=${notation}`);
+}
+
+const options = new Intl.NumberFormat([], {
+ notation: "compact",
+ compactDisplay: "long",
+}).resolvedOptions();
+assert.sameValue("compactDisplay" in options, true, "There should be a compactDisplay property with notation=compact");
+assert.sameValue(options.compactDisplay, "long", "The compactDisplay property should be defined with notation=compact");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/length.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/length.js
new file mode 100644
index 0000000000..44fb64a705
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/length.js
@@ -0,0 +1,34 @@
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.resolvedoptions
+description: >
+ Intl.NumberFormat.prototype.resolvedOptions.length is 0.
+info: |
+ Intl.NumberFormat.prototype.resolvedOptions ()
+
+ 17 ECMAScript Standard Built-in Objects:
+
+ Every built-in function object, including constructors, has a length
+ property whose value is an integer. Unless otherwise specified, this
+ value is equal to the largest number of named arguments shown in the
+ subclause headings for the function description. Optional parameters
+ (which are indicated with brackets: [ ]) or rest parameters (which
+ are shown using the form «...name») are not included in the default
+ argument count.
+ Unless otherwise specified, the length property of a built-in function
+ object has the attributes { [[Writable]]: false, [[Enumerable]]: false,
+ [[Configurable]]: true }.
+
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Intl.NumberFormat.prototype.resolvedOptions, "length", {
+ value: 0,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/name.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/name.js
new file mode 100644
index 0000000000..584e60f57d
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/name.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2016 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat.prototype.resolvedOptions
+description: >
+ Intl.NumberFormat.prototype.resolvedOptions.name is "resolvedOptions".
+info: |
+ 11.4.4 Intl.NumberFormat.prototype.resolvedOptions ()
+
+ 17 ECMAScript Standard Built-in Objects:
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value
+ is a String.
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Intl.NumberFormat.prototype.resolvedOptions, "name", {
+ value: "resolvedOptions",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/no-instanceof.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/no-instanceof.js
new file mode 100644
index 0000000000..e1be473f7d
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/no-instanceof.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 Igalia S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.resolvedoptions
+description: >
+ Tests that Intl.NumberFormat.prototype.resolvedOptions calls
+ OrdinaryHasInstance instead of the instanceof operator which includes a
+ Symbol.hasInstance lookup and call among other things.
+info: >
+ UnwrapNumberFormat ( nf )
+
+ 2. If nf does not have an [[InitializedNumberFormat]] internal slot and
+ ? OrdinaryHasInstance(%NumberFormat%, nf) is true, then
+ a. Return ? Get(nf, %Intl%.[[FallbackSymbol]]).
+---*/
+
+const nf = Object.create(Intl.NumberFormat.prototype);
+
+Object.defineProperty(Intl.NumberFormat, Symbol.hasInstance, {
+ get() { throw new Test262Error(); }
+});
+
+assert.throws(TypeError, () => nf.resolvedOptions());
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/order.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/order.js
new file mode 100644
index 0000000000..16f35fb743
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/order.js
@@ -0,0 +1,43 @@
+// Copyright 2018 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.resolvedoptions
+description: Verifies the property order for the object returned by resolvedOptions().
+features: [Intl.NumberFormat-unified]
+---*/
+
+const options = new Intl.NumberFormat([], {
+ "style": "currency",
+ "currency": "EUR",
+ "currencyDisplay": "symbol",
+ "minimumSignificantDigits": 1,
+ "maximumSignificantDigits": 2,
+}).resolvedOptions();
+
+const expected = [
+ "locale",
+ "numberingSystem",
+ "style",
+ "currency",
+ "currencyDisplay",
+ "currencySign",
+ "minimumIntegerDigits",
+ "minimumSignificantDigits",
+ "maximumSignificantDigits",
+ "useGrouping",
+ "notation",
+ "signDisplay",
+];
+
+const actual = Object.getOwnPropertyNames(options);
+
+// Ensure all expected items are in actual and also allow other properties
+// implemented in new proposals.
+assert(actual.indexOf("locale") > -1, "\"locale\" is present");
+for (var i = 1; i < expected.length; i++) {
+ // Ensure the order as expected but allow additional new property in between
+ assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i]), `"${expected[i-1]}" precedes "${expected[i]}"`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/prop-desc.js
new file mode 100644
index 0000000000..d871d8b225
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/prop-desc.js
@@ -0,0 +1,33 @@
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.resolvedoptions
+description: >
+ "resolvedOptions" property of Intl.NumberFormat.prototype.
+info: |
+ Intl.NumberFormat.prototype.resolvedOptions ()
+
+ 7 Requirements for Standard Built-in ECMAScript Objects
+
+ Unless specified otherwise in this document, the objects, functions, and constructors
+ described in this standard are subject to the generic requirements and restrictions
+ specified for standard built-in ECMAScript objects in the ECMAScript 2018 Language
+ Specification, 9th edition, clause 17, or successor.
+
+ 17 ECMAScript Standard Built-in Objects:
+
+ Every other data property described in clauses 18 through 26 and in Annex B.2 has the
+ attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }
+ unless otherwise specified.
+
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Intl.NumberFormat.prototype, "resolvedOptions", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/return-keys-order-default.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/return-keys-order-default.js
new file mode 100644
index 0000000000..15ad912032
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/return-keys-order-default.js
@@ -0,0 +1,49 @@
+// Copyright 2023 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.resolvedoptions
+description: order of property keys for the object returned by resolvedOptions()
+features: [Intl.NumberFormat-v3]
+includes: [compareArray.js]
+---*/
+
+const allKeys = [
+ 'locale',
+ 'numberingSystem',
+ 'style',
+ 'currency',
+ 'currencyDisplay',
+ 'currencySign',
+ 'unit',
+ 'unitDisplay',
+ 'minimumIntegerDigits',
+ 'minimumFractionDigits',
+ 'maximumFractionDigits',
+ 'minimumSignificantDigits',
+ 'maximumSignificantDigits',
+ 'useGrouping',
+ 'notation',
+ 'compactDisplay',
+ 'signDisplay',
+ 'roundingIncrement',
+ 'roundingMode',
+ 'roundingPriority',
+ 'trailingZeroDisplay'
+];
+
+const optionsBase = { notation: 'compact' };
+const optionsExtensions = [
+ { style: 'currency', currency: 'XTS' },
+ { style: 'unit', unit: 'percent' },
+];
+optionsExtensions.forEach((optionsExtension) => {
+ const options = Object.assign({}, optionsBase, optionsExtension);
+ const nf = new Intl.NumberFormat(undefined, options);
+ const resolved = nf.resolvedOptions();
+ const resolvedKeys = Reflect.ownKeys(resolved);
+ const expectedKeys = allKeys.filter(key => key in resolved);
+ assert.compareArray(resolvedKeys, expectedKeys,
+ 'resolvedOptions() property key order with options ' + JSON.stringify(options));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/roundingMode.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/roundingMode.js
new file mode 100644
index 0000000000..10ab976f1c
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/roundingMode.js
@@ -0,0 +1,42 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// Copyright 2021 Apple Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat.prototype.resolvedoptions
+description: roundingMode property for the object returned by resolvedOptions()
+features: [Intl.NumberFormat-v3]
+---*/
+
+var options;
+
+options = new Intl.NumberFormat([], {}).resolvedOptions();
+assert.sameValue(options.roundingMode, 'halfExpand', 'default');
+
+options = new Intl.NumberFormat([], {roundingMode: 'ceil'}).resolvedOptions();
+assert.sameValue(options.roundingMode, 'ceil');
+
+options = new Intl.NumberFormat([], {roundingMode: 'floor'}).resolvedOptions();
+assert.sameValue(options.roundingMode, 'floor');
+
+options = new Intl.NumberFormat([], {roundingMode: 'expand'}).resolvedOptions();
+assert.sameValue(options.roundingMode, 'expand');
+
+options = new Intl.NumberFormat([], {roundingMode: 'trunc'}).resolvedOptions();
+assert.sameValue(options.roundingMode, 'trunc');
+
+options = new Intl.NumberFormat([], {roundingMode: 'halfCeil'}).resolvedOptions();
+assert.sameValue(options.roundingMode, 'halfCeil');
+
+options = new Intl.NumberFormat([], {roundingMode: 'halfFloor'}).resolvedOptions();
+assert.sameValue(options.roundingMode, 'halfFloor');
+
+options = new Intl.NumberFormat([], {roundingMode: 'halfExpand'}).resolvedOptions();
+assert.sameValue(options.roundingMode, 'halfExpand');
+
+options = new Intl.NumberFormat([], {roundingMode: 'halfTrunc'}).resolvedOptions();
+assert.sameValue(options.roundingMode, 'halfTrunc');
+
+options = new Intl.NumberFormat([], {roundingMode: 'halfEven'}).resolvedOptions();
+assert.sameValue(options.roundingMode, 'halfEven');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/shell.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/shell.js
@@ -0,0 +1,24 @@
+// GENERATED, DO NOT EDIT
+// file: isConstructor.js
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: |
+ Test if a given function is a constructor function.
+defines: [isConstructor]
+features: [Reflect.construct]
+---*/
+
+function isConstructor(f) {
+ if (typeof f !== "function") {
+ throw new Test262Error("isConstructor invoked with a non-function value");
+ }
+
+ try {
+ Reflect.construct(function(){}, [], f);
+ } catch (e) {
+ return false;
+ }
+ return true;
+}
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/this-value-not-numberformat.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/this-value-not-numberformat.js
new file mode 100644
index 0000000000..d9773f00a3
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/this-value-not-numberformat.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2018 Ujjwal Sharma. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat.prototype.resolvedOptions
+description: >
+ Tests that Intl.NumberFormat.prototype.resolvedOptions throws a
+ TypeError if called on a non-object value or an object that hasn't
+ been initialized as a NumberFormat.
+---*/
+
+const invalidTargets = [undefined, null, true, 0, 'NumberFormat', [], {}, Symbol()];
+const fn = Intl.NumberFormat.prototype.resolvedOptions;
+
+invalidTargets.forEach(target => {
+ assert.throws(
+ TypeError,
+ () => fn.call(target),
+ `Calling resolvedOptions on ${String(target)} should throw a TypeError.`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/shell.js b/js/src/tests/test262/intl402/NumberFormat/prototype/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/shell.js
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/this-value-numberformat-prototype.js b/js/src/tests/test262/intl402/NumberFormat/prototype/this-value-numberformat-prototype.js
new file mode 100644
index 0000000000..8fed1e229a
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/this-value-numberformat-prototype.js
@@ -0,0 +1,17 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-properties-of-intl-numberformat-prototype-object
+description: >
+ Tests that Intl.NumberFormat.prototype is not an object that has been
+ initialized as an Intl.NumberFormat.
+author: Roozbeh Pournader
+---*/
+
+// test by calling a function that should fail as "this" is not an object
+// initialized as an Intl.NumberFormat
+assert.throws(TypeError, () => Intl.NumberFormat.prototype.format(0),
+ "Intl.NumberFormat's prototype is not an object that has been initialized as an Intl.NumberFormat");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/browser.js b/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/browser.js
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/configurable.js b/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/configurable.js
new file mode 100644
index 0000000000..a6aa44d04a
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/configurable.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2018 Ujjwal Sharma. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype-@@tostringtag
+description: >
+ Check that the initial value of the property is "Intl.NumberFormat" and that any changes
+ made by reconfiguring are reflected.
+---*/
+
+assert.sameValue(Intl.NumberFormat.prototype[Symbol.toStringTag], 'Intl.NumberFormat');
+assert.sameValue(
+ Object.prototype.toString.call(new Intl.NumberFormat()),
+ '[object Intl.NumberFormat]'
+);
+
+Object.defineProperty(Intl.NumberFormat.prototype, Symbol.toStringTag, {
+ value: 'Alpha'
+});
+
+assert.sameValue(Intl.NumberFormat.prototype[Symbol.toStringTag], 'Alpha');
+assert.sameValue(
+ Object.prototype.toString.call(new Intl.NumberFormat()),
+ '[object Alpha]'
+);
+
+delete Intl.NumberFormat.prototype[Symbol.toStringTag];
+
+assert.sameValue(Intl.NumberFormat.prototype[Symbol.toStringTag], undefined);
+assert.sameValue(
+ Object.prototype.toString.call(new Intl.NumberFormat()),
+ '[object Object]'
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/prop-desc.js
new file mode 100644
index 0000000000..e5116e6dec
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/prop-desc.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2018 Ujjwal Sharma. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype-@@tostringtag
+description: >
+ Tests that Intl.NumberFormat.prototype[@@toStringTag] has the required attributes.
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Intl.NumberFormat.prototype, Symbol.toStringTag, {
+ value: 'Intl.NumberFormat',
+ writable: false,
+ enumerable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/shell.js b/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/shell.js
diff --git a/js/src/tests/test262/intl402/NumberFormat/shell.js b/js/src/tests/test262/intl402/NumberFormat/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/shell.js
diff --git a/js/src/tests/test262/intl402/NumberFormat/significant-digits-options-get-sequence.js b/js/src/tests/test262/intl402/NumberFormat/significant-digits-options-get-sequence.js
new file mode 100644
index 0000000000..0602e55b9c
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/significant-digits-options-get-sequence.js
@@ -0,0 +1,42 @@
+// Copyright 2013 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.1.1_32
+description: >
+ Tests that the options minimumSignificantDigits and
+ maximumSignificantDigits are read in the right sequence.
+author: Norbert Lindenberg
+---*/
+
+var minimumSignificantDigitsRead = false;
+var maximumSignificantDigitsRead = false;
+
+function readMinimumSignificantDigits() {
+ assert.sameValue(minimumSignificantDigitsRead, false,
+ "minimumSignificantDigits getter already called");
+ assert.sameValue(maximumSignificantDigitsRead, false,
+ "maximumSignificantDigits getter called before minimumSignificantDigits");
+ minimumSignificantDigitsRead = true;
+ return 1;
+}
+
+function readMaximumSignificantDigits() {
+ assert.sameValue(maximumSignificantDigitsRead, false,
+ "maximumSignificantDigits getter already called");
+ maximumSignificantDigitsRead = true;
+ return 1;
+}
+
+var options = {};
+Object.defineProperty(options, "minimumSignificantDigits",
+ { get: readMinimumSignificantDigits });
+Object.defineProperty(options, "maximumSignificantDigits",
+ { get: readMaximumSignificantDigits });
+
+new Intl.NumberFormat("de", options);
+
+assert(minimumSignificantDigitsRead, "minimumSignificantDigits getter was called once");
+assert(maximumSignificantDigitsRead, "maximumSignificantDigits getter was called once");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/style-unit.js b/js/src/tests/test262/intl402/NumberFormat/style-unit.js
new file mode 100644
index 0000000000..f41406dcfe
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/style-unit.js
@@ -0,0 +1,28 @@
+// Copyright 2018 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-setnumberformatunitoptions
+description: Checks handling of valid values for the numeric option to the RelativeTimeFormat constructor.
+info: |
+ SetNumberFormatUnitOptions ( intlObj, options )
+
+ 3. Let style be ? GetOption(options, "style", "string", « "decimal", "percent", "currency", "unit" », "decimal").
+ 4. Set intlObj.[[Style]] to style.
+
+features: [Intl.NumberFormat-unified]
+---*/
+
+const validOptions = [
+ [undefined, "decimal"],
+ ["unit", "unit"],
+ [{ toString() { return "unit"; } }, "unit"],
+];
+
+for (const [validOption, expected] of validOptions) {
+ const nf = new Intl.NumberFormat([], {"style": validOption, "unit": "gigabit"});
+ const resolvedOptions = nf.resolvedOptions();
+ assert.sameValue(resolvedOptions.style, expected);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/subclassing.js b/js/src/tests/test262/intl402/NumberFormat/subclassing.js
new file mode 100644
index 0000000000..e143233d50
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/subclassing.js
@@ -0,0 +1,30 @@
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.1.2
+description: Tests that Intl.NumberFormat can be subclassed.
+author: Norbert Lindenberg
+includes: [compareArray.js]
+---*/
+
+// get a number format and have it format an array of numbers for comparison with the subclass
+var locales = ["tlh", "id", "en"];
+var a = [0, 1, -1, -123456.789, -Infinity, NaN];
+var referenceNumberFormat = new Intl.NumberFormat(locales);
+var referenceFormatted = a.map(referenceNumberFormat.format);
+
+class MyNumberFormat extends Intl.NumberFormat {
+ constructor(locales, options) {
+ super(locales, options);
+ // could initialize MyNumberFormat properties
+ }
+ // could add methods to MyNumberFormat.prototype
+}
+
+var format = new MyNumberFormat(locales);
+var actual = a.map(format.format);
+assert.compareArray(actual, referenceFormatted);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/basic.js b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/basic.js
new file mode 100644
index 0000000000..fbf53ad990
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/basic.js
@@ -0,0 +1,25 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.2.2_a
+description: >
+ Tests that Intl.NumberFormat has a supportedLocalesOf property,
+ and it works as planned.
+author: Roozbeh Pournader
+---*/
+
+var defaultLocale = new Intl.NumberFormat().resolvedOptions().locale;
+var notSupported = 'zxx'; // "no linguistic content"
+var requestedLocales = [defaultLocale, notSupported];
+
+var supportedLocales;
+
+assert(Intl.NumberFormat.hasOwnProperty('supportedLocalesOf'), "Intl.NumberFormat doesn't have a supportedLocalesOf property.");
+
+supportedLocales = Intl.NumberFormat.supportedLocalesOf(requestedLocales);
+assert.sameValue(supportedLocales.length, 1, 'The length of supported locales list is not 1.');
+
+assert.sameValue(supportedLocales[0], defaultLocale, 'The default locale is not returned in the supported list.');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/browser.js b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/browser.js
diff --git a/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/builtin.js b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/builtin.js
new file mode 100644
index 0000000000..0c5efac8c5
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/builtin.js
@@ -0,0 +1,30 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+es5id: 11.2.2_L15
+description: >
+ Tests that Intl.NumberFormat.supportedLocalesOf meets the
+ requirements for built-in objects defined by the introduction of
+ chapter 17 of the ECMAScript Language Specification.
+author: Norbert Lindenberg
+includes: [isConstructor.js]
+features: [Reflect.construct]
+---*/
+
+assert.sameValue(Object.prototype.toString.call(Intl.NumberFormat.supportedLocalesOf), "[object Function]",
+ "The [[Class]] internal property of a built-in function must be " +
+ "\"Function\".");
+
+assert(Object.isExtensible(Intl.NumberFormat.supportedLocalesOf),
+ "Built-in objects must be extensible.");
+
+assert.sameValue(Object.getPrototypeOf(Intl.NumberFormat.supportedLocalesOf), Function.prototype);
+
+assert.sameValue(Intl.NumberFormat.supportedLocalesOf.hasOwnProperty("prototype"), false,
+ "Built-in functions that aren't constructors must not have a prototype property.");
+
+assert.sameValue(isConstructor(Intl.NumberFormat.supportedLocalesOf), false,
+ "Built-in functions don't implement [[Construct]] unless explicitly specified.");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/length.js b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/length.js
new file mode 100644
index 0000000000..e18f05e14b
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/length.js
@@ -0,0 +1,34 @@
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.supportedlocalesof
+description: >
+ Intl.NumberFormat.supportedLocalesOf.length is 1.
+info: |
+ Intl.NumberFormat.supportedLocalesOf ( locales [ , options ] )
+
+ 17 ECMAScript Standard Built-in Objects:
+
+ Every built-in function object, including constructors, has a length
+ property whose value is an integer. Unless otherwise specified, this
+ value is equal to the largest number of named arguments shown in the
+ subclause headings for the function description. Optional parameters
+ (which are indicated with brackets: [ ]) or rest parameters (which
+ are shown using the form «...name») are not included in the default
+ argument count.
+ Unless otherwise specified, the length property of a built-in function
+ object has the attributes { [[Writable]]: false, [[Enumerable]]: false,
+ [[Configurable]]: true }.
+
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Intl.NumberFormat.supportedLocalesOf, "length", {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/name.js b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/name.js
new file mode 100644
index 0000000000..8abc567de5
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/name.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2016 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-Intl.NumberFormat.supportedLocalesOf
+description: >
+ Intl.NumberFormat.supportedLocalesOf.name is "supportedLocalesOf".
+info: |
+ 11.3.2 Intl.NumberFormat.supportedLocalesOf (locales [ , options ])
+
+ 17 ECMAScript Standard Built-in Objects:
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value
+ is a String.
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Intl.NumberFormat.supportedLocalesOf, "name", {
+ value: "supportedLocalesOf",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/prop-desc.js
new file mode 100644
index 0000000000..d6476db47e
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/prop-desc.js
@@ -0,0 +1,33 @@
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.supportedlocalesof
+description: >
+ "supportedLocalesOf" property of Intl.NumberFormat.
+info: |
+ Intl.NumberFormat.supportedLocalesOf ( locales [ , options ] )
+
+ 7 Requirements for Standard Built-in ECMAScript Objects
+
+ Unless specified otherwise in this document, the objects, functions, and constructors
+ described in this standard are subject to the generic requirements and restrictions
+ specified for standard built-in ECMAScript objects in the ECMAScript 2018 Language
+ Specification, 9th edition, clause 17, or successor.
+
+ 17 ECMAScript Standard Built-in Objects:
+
+ Every other data property described in clauses 18 through 26 and in Annex B.2 has the
+ attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }
+ unless otherwise specified.
+
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Intl.NumberFormat, "supportedLocalesOf", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/shell.js b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/shell.js
@@ -0,0 +1,24 @@
+// GENERATED, DO NOT EDIT
+// file: isConstructor.js
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: |
+ Test if a given function is a constructor function.
+defines: [isConstructor]
+features: [Reflect.construct]
+---*/
+
+function isConstructor(f) {
+ if (typeof f !== "function") {
+ throw new Test262Error("isConstructor invoked with a non-function value");
+ }
+
+ try {
+ Reflect.construct(function(){}, [], f);
+ } catch (e) {
+ return false;
+ }
+ return true;
+}
diff --git a/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/taint-Object-prototype.js b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/taint-Object-prototype.js
new file mode 100644
index 0000000000..d8644585e4
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/taint-Object-prototype.js
@@ -0,0 +1,16 @@
+// Copyright 2013 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/*---
+es5id: 11.2.2_b
+description: >
+ Tests that Intl.NumberFormat.supportedLocalesOf doesn't access
+ arguments that it's not given.
+author: Norbert Lindenberg
+includes: [testIntl.js]
+---*/
+
+taintDataProperty(Object.prototype, "1");
+new Intl.NumberFormat("und");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/taint-Object-prototype.js b/js/src/tests/test262/intl402/NumberFormat/taint-Object-prototype.js
new file mode 100644
index 0000000000..19a41731d8
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/taint-Object-prototype.js
@@ -0,0 +1,18 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.1.1_6
+description: >
+ Tests that the behavior of a Record is not affected by
+ adversarial changes to Object.prototype.
+author: Norbert Lindenberg
+includes: [testIntl.js]
+---*/
+
+taintProperties(["localeMatcher"]);
+
+var locale = new Intl.NumberFormat(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale;
+assert(isCanonicalizedStructurallyValidLanguageTag(locale), "NumberFormat returns invalid locale " + locale + ".");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/test-option-currency.js b/js/src/tests/test262/intl402/NumberFormat/test-option-currency.js
new file mode 100644
index 0000000000..d1d786fab1
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/test-option-currency.js
@@ -0,0 +1,57 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.1.1_17
+description: Tests that the option currency is processed correctly.
+author: Norbert Lindenberg
+---*/
+
+var validValues = ["CNY", "USD", "EUR", "IDR", "jpy", {toString: function () {return "INR";}}];
+var invalidValues = ["$", "SFr.", "US$", "ßP", {toString: function () {return;}}];
+
+var defaultLocale = new Intl.NumberFormat().resolvedOptions().locale;
+
+validValues.forEach(function (value) {
+ var format, actual, expected;
+
+ // with currency style, we should get the upper case form back
+ format = new Intl.NumberFormat([defaultLocale], {style: "currency", currency: value});
+ actual = format.resolvedOptions().currency;
+ expected = value.toString().toUpperCase();
+ assert.sameValue(actual, expected, "Incorrect resolved currency with currency style.");
+
+ // without currency style, we shouldn't get any currency back
+ format = new Intl.NumberFormat([defaultLocale], {currency: value});
+ actual = format.resolvedOptions().currency;
+ expected = undefined;
+ assert.sameValue(actual, expected, "Incorrect resolved currency with non-currency style.");
+
+ // currencies specified through the locale must be ignored
+ format = new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {style: "currency", currency: value});
+ actual = format.resolvedOptions().currency;
+ expected = value.toString().toUpperCase();
+ assert.sameValue(actual, expected, "Incorrect resolved currency with -u-cu- and currency style.");
+
+ format = new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {currency: value});
+ actual = format.resolvedOptions().currency;
+ expected = undefined;
+ assert.sameValue(actual, expected, "Incorrect resolved currency with -u-cu- and non-currency style.");
+});
+
+invalidValues.forEach(function (value) {
+ assert.throws(RangeError, function () {
+ return new Intl.NumberFormat([defaultLocale], {style: "currency", currency: value});
+ }, "Invalid currency value " + value + " was not rejected.");
+ assert.throws(RangeError, function () {
+ return new Intl.NumberFormat([defaultLocale], {currency: value});
+ }, "Invalid currency value " + value + " was not rejected.");
+ assert.throws(RangeError, function () {
+ return new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {style: "currency", currency: value});
+ }, "Invalid currency value " + value + " was not rejected.");
+ assert.throws(RangeError, function () {
+ return new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {currency: value});
+ }, "Invalid currency value " + value + " was not rejected.");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/test-option-currencyDisplay.js b/js/src/tests/test262/intl402/NumberFormat/test-option-currencyDisplay.js
new file mode 100644
index 0000000000..afc92c1151
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/test-option-currencyDisplay.js
@@ -0,0 +1,16 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.1.1_21
+description: Tests that the option currencyDisplay is processed correctly.
+author: Norbert Lindenberg
+includes: [testIntl.js]
+---*/
+
+testOption(Intl.NumberFormat, "currencyDisplay", "string", ["code", "symbol", "name"],
+ "symbol", {extra: {any: {style: "currency", currency: "XDR"}}});
+testOption(Intl.NumberFormat, "currencyDisplay", "string", ["code", "symbol", "name"],
+ undefined, {noReturn: true});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/test-option-localeMatcher.js b/js/src/tests/test262/intl402/NumberFormat/test-option-localeMatcher.js
new file mode 100644
index 0000000000..b2525bc392
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/test-option-localeMatcher.js
@@ -0,0 +1,13 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.1.1_7
+description: Tests that the option localeMatcher is processed correctly.
+author: Norbert Lindenberg
+includes: [testIntl.js]
+---*/
+
+testOption(Intl.NumberFormat, "localeMatcher", "string", ["lookup", "best fit"], "best fit", {noReturn: true});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/test-option-roundingPriority-mixed-options.js b/js/src/tests/test262/intl402/NumberFormat/test-option-roundingPriority-mixed-options.js
new file mode 100644
index 0000000000..211be9d4c9
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/test-option-roundingPriority-mixed-options.js
@@ -0,0 +1,96 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl.numberformat.prototype.format
+description: Tests that the digits are determined correctly when specifying at same time «"minimumFractionDigits", "maximumFractionDigits", "minimumSignificantDigits", "maximumSignificantDigits"»
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+const locales = [new Intl.NumberFormat().resolvedOptions().locale, 'ar', 'de', 'th', 'ja'];
+
+const numberingSystems = ['arab', 'latn', 'thai', 'hanidec'];
+
+const expectedResults = {
+ 'morePrecision': {
+ 'same-minimums': { '1': '1.0', '1.500': '1.5', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2.0' },
+ 'same-maximums': { '1': '1', '1.500': '1.5', '1.625': '1.63', '1.750': '1.75', '1.875': '1.88', '2.000': '2' },
+ 'minSd-larger-minFd': { '1': '1.00', '1.500': '1.50', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2.00' },
+ 'minSd-smaller-minFd': { '1': '1', '1.500': '1.5', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2' },
+ 'minSd-smaller-maxFd': { '1': '1', '1.500': '1.5', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2' },
+ 'minSd-larger-maxFd': { '1': '1.00', '1.500': '1.50', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2.00' },
+ 'maxSd-larger-minFd': { '1': '1.0', '1.500': '1.5', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2.0' },
+ 'maxSd-smaller-minFd': { '1': '1.000', '1.500': '1.500', '1.625': '1.625', '1.750': '1.750', '1.875': '1.875', '2.000': '2.000' },
+ 'maxSd-smaller-maxFd': { '1': '1', '1.500': '1.5', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2' },
+ 'maxSd-larger-maxFd': { '1': '1', '1.500': '1.5', '1.625': '1.63', '1.750': '1.75', '1.875': '1.88', '2.000': '2' },
+ 'minSd-maxSd-smaller-minFd-maxFd': { '1': '1.000', '1.500': '1.500', '1.625': '1.625', '1.750': '1.750', '1.875': '1.875', '2.000': '2.000' },
+ 'minSd-maxSd-larger-minFd-maxFd': { '1': '1.00', '1.500': '1.50', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2.00' },
+ 'same-minimums-maxFd-larger-maxSd': { '1': '1.0', '1.500': '1.5', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2.0' },
+ 'same-minimums-maxFd-smaller-maxSd': { '1': '1', '1.500': '1.5', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2' },
+ },
+ 'lessPrecision': {
+ 'same-minimums': { '1': '1.00', '1.500': '1.50', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2.00' },
+ 'same-maximums': { '1': '1', '1.500': '1.5', '1.625': '1.6', '1.750': '1.8', '1.875': '1.9', '2.000': '2' },
+ 'minSd-larger-minFd': { '1': '1.0', '1.500': '1.5', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2.0' },
+ 'minSd-smaller-minFd': { '1': '1.000', '1.500': '1.500', '1.625': '1.625', '1.750': '1.750', '1.875': '1.875', '2.000': '2.000' },
+ 'minSd-smaller-maxFd': { '1': '1', '1.500': '1.5', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2' },
+ 'minSd-larger-maxFd': { '1': '1', '1.500': '1.5', '1.625': '1.6', '1.750': '1.8', '1.875': '1.9', '2.000': '2' },
+ 'maxSd-larger-minFd': { '1': '1', '1.500': '1.5', '1.625': '1.63', '1.750': '1.75', '1.875': '1.88', '2.000': '2' },
+ 'maxSd-smaller-minFd': { '1': '1', '1.500': '1.5', '1.625': '1.6', '1.750': '1.8', '1.875': '1.9', '2.000': '2' },
+ 'maxSd-smaller-maxFd': { '1': '1', '1.500': '1.5', '1.625': '1.6', '1.750': '1.8', '1.875': '1.9', '2.000': '2' },
+ 'maxSd-larger-maxFd': { '1': '1', '1.500': '1.5', '1.625': '1.6', '1.750': '1.8', '1.875': '1.9', '2.000': '2' },
+ 'minSd-maxSd-smaller-minFd-maxFd': { '1': '1', '1.500': '1.5', '1.625': '1.6', '1.750': '1.8', '1.875': '1.9', '2.000': '2' },
+ 'minSd-maxSd-larger-minFd-maxFd': { '1': '1.0', '1.500': '1.5', '1.625': '1.63', '1.750': '1.75', '1.875': '1.88', '2.000': '2.0' },
+ 'same-minimums-maxFd-larger-maxSd': { '1': '1', '1.500': '1.5', '1.625': '1.6', '1.750': '1.8', '1.875': '1.9', '2.000': '2' },
+ 'same-minimums-maxFd-smaller-maxSd': { '1': '1.0', '1.500': '1.5', '1.625': '1.63', '1.750': '1.75', '1.875': '1.88', '2.000': '2.0' },
+ },
+ 'auto': {
+ 'same-minimums': { '1': '1.0', '1.500': '1.5', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2.0' },
+ 'same-maximums': { '1': '1', '1.500': '1.5', '1.625': '1.6', '1.750': '1.8', '1.875': '1.9', '2.000': '2' },
+ 'minSd-larger-minFd': { '1': '1.00', '1.500': '1.50', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2.00' },
+ 'minSd-smaller-minFd': { '1': '1', '1.500': '1.5', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2' },
+ 'minSd-smaller-maxFd': { '1': '1', '1.500': '1.5', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2' },
+ 'minSd-larger-maxFd': { '1': '1.00', '1.500': '1.50', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2.00' },
+ 'maxSd-larger-minFd': { '1': '1', '1.500': '1.5', '1.625': '1.63', '1.750': '1.75', '1.875': '1.88', '2.000': '2' },
+ 'maxSd-smaller-minFd': { '1': '1', '1.500': '1.5', '1.625': '1.6', '1.750': '1.8', '1.875': '1.9', '2.000': '2' },
+ 'maxSd-smaller-maxFd': { '1': '1', '1.500': '1.5', '1.625': '1.6', '1.750': '1.8', '1.875': '1.9', '2.000': '2' },
+ 'maxSd-larger-maxFd': { '1': '1', '1.500': '1.5', '1.625': '1.63', '1.750': '1.75', '1.875': '1.88', '2.000': '2' },
+ 'minSd-maxSd-smaller-minFd-maxFd': { '1': '1', '1.500': '1.5', '1.625': '1.6', '1.750': '1.8', '1.875': '1.9', '2.000': '2' },
+ 'minSd-maxSd-larger-minFd-maxFd': { '1': '1.00', '1.500': '1.50', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2.00' },
+ 'same-minimums-maxFd-larger-maxSd': { '1': '1', '1.500': '1.5', '1.625': '1.6', '1.750': '1.8', '1.875': '1.9', '2.000': '2' },
+ 'same-minimums-maxFd-smaller-maxSd': { '1': '1', '1.500': '1.5', '1.625': '1.625', '1.750': '1.75', '1.875': '1.875', '2.000': '2' },
+ },
+};
+
+const optionsMatrix = {
+ 'same-minimums': { minimumSignificantDigits: 2, minimumFractionDigits: 2 },
+ 'same-maximums': { maximumSignificantDigits: 2, maximumFractionDigits: 2 },
+ 'minSd-larger-minFd': { minimumSignificantDigits: 3, minimumFractionDigits: 1 },
+ 'minSd-smaller-minFd': { minimumSignificantDigits: 1, minimumFractionDigits: 3 },
+ 'minSd-smaller-maxFd': { minimumSignificantDigits: 1, maximumFractionDigits: 3 },
+ 'minSd-larger-maxFd': { minimumSignificantDigits: 3, maximumFractionDigits: 1 },
+ 'maxSd-larger-minFd': { maximumSignificantDigits: 3, minimumFractionDigits: 1 },
+ 'maxSd-smaller-minFd': { maximumSignificantDigits: 2, minimumFractionDigits: 3 },
+ 'maxSd-smaller-maxFd': { maximumSignificantDigits: 2, maximumFractionDigits: 3 },
+ 'maxSd-larger-maxFd': { maximumSignificantDigits: 3, maximumFractionDigits: 1 },
+ 'minSd-maxSd-smaller-minFd-maxFd': { minimumSignificantDigits: 1, maximumSignificantDigits: 2, minimumFractionDigits: 3, maximumFractionDigits: 4 },
+ 'minSd-maxSd-larger-minFd-maxFd': { minimumSignificantDigits: 3, maximumSignificantDigits: 4, minimumFractionDigits: 1, maximumFractionDigits: 2 },
+ 'same-minimums-maxFd-larger-maxSd': { minimumSignificantDigits: 1, maximumSignificantDigits: 2, minimumFractionDigits: 1, maximumFractionDigits: 4 },
+ 'same-minimums-maxFd-smaller-maxSd': { minimumSignificantDigits: 1, maximumSignificantDigits: 4, minimumFractionDigits: 1, maximumFractionDigits: 2 },
+};
+
+function testPrecision(mode) {
+ Object.keys(optionsMatrix).forEach((key) => {
+ testNumberFormat(
+ locales,
+ numberingSystems,
+ { ...optionsMatrix[key], roundingPriority: mode, userGrouping: false },
+ expectedResults[mode][key]
+ );
+ });
+}
+
+['morePrecision', 'lessPrecision', 'auto'].forEach(testPrecision);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/test-option-roundingPriority.js b/js/src/tests/test262/intl402/NumberFormat/test-option-roundingPriority.js
new file mode 100644
index 0000000000..afe01335fb
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/test-option-roundingPriority.js
@@ -0,0 +1,18 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-intl.numberformat
+description: Tests that the option roundingPriority is processed correctly.
+features: [Intl.NumberFormat-v3]
+includes: [testIntl.js]
+---*/
+
+testOption(
+ Intl.NumberFormat,
+ "roundingPriority",
+ "string",
+ ["auto", "morePrecision", "lessPrecision"],
+ "auto"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/test-option-style.js b/js/src/tests/test262/intl402/NumberFormat/test-option-style.js
new file mode 100644
index 0000000000..fd9063b490
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/test-option-style.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.1.1_15
+description: Tests that the option style is processed correctly.
+author: Norbert Lindenberg
+includes: [testIntl.js]
+---*/
+
+testOption(Intl.NumberFormat, "style", "string", ["decimal", "percent", "currency"], "decimal",
+ {extra: {"currency": {currency: "CNY"}}});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping-extended.js b/js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping-extended.js
new file mode 100644
index 0000000000..abead17ffd
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping-extended.js
@@ -0,0 +1,41 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// Copyright 2022 Apple Inc. All rights reserved.
+// Copyright 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: Tests that the option useGrouping is processed correctly.
+info: |
+ The "Intl.NumberFormat v3" proposal contradicts the behavior required by the
+ latest revision of ECMA402.
+features: [Intl.NumberFormat-v3]
+---*/
+
+function render(options) {
+ var nf = new Intl.NumberFormat(undefined, options);
+ return nf.resolvedOptions().useGrouping;
+}
+
+assert.sameValue(render({}), 'auto', '(omitted)');
+assert.sameValue(render({useGrouping: undefined}), 'auto', 'undefined');
+assert.sameValue(render({useGrouping: 'auto'}), 'auto', '"auto"');
+assert.sameValue(render({useGrouping: true}), 'always', 'true');
+assert.sameValue(render({useGrouping: 'always'}), 'always', '"always"');
+assert.sameValue(render({useGrouping: false}), false, 'false');
+assert.sameValue(render({useGrouping: null}), false, 'null');
+assert.sameValue(render({useGrouping: 'min2'}), 'min2', '"min2"');
+
+assert.sameValue(render({notation: 'compact'}), 'min2', 'compact, (omitted)');
+assert.sameValue(render({notation: 'compact', useGrouping: undefined}), 'min2', 'compact, undefined');
+assert.sameValue(render({notation: 'compact', useGrouping: 'auto'}), 'auto', 'compact, "auto"');
+assert.sameValue(render({notation: 'compact', useGrouping: true}), 'always', 'compact, true');
+assert.sameValue(render({notation: 'compact', useGrouping: 'always'}), 'always', 'compact, "always"');
+assert.sameValue(render({notation: 'compact', useGrouping: false}), false, 'compact, false');
+assert.sameValue(render({notation: 'compact', useGrouping: null}), false, 'compact, null');
+assert.sameValue(render({notation: 'compact', useGrouping: 'min2'}), 'min2', 'compact, "min2"');
+
+assert.sameValue(render({useGrouping: 'false'}), 'auto', 'use fallback value');
+assert.sameValue(render({useGrouping: 'true'}), 'auto', 'use fallback value');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping.js b/js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping.js
new file mode 100644
index 0000000000..13e1df9ab9
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping.js
@@ -0,0 +1,42 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// Copyright 2022 Apple Inc. All rights reserved.
+// Copyright 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.1.1_34
+description: Tests that the option useGrouping is processed correctly.
+info: |
+ The "Intl.NumberFormat v3" proposal contradicts the behavior required by the
+ latest revision of ECMA402.
+author: Norbert Lindenberg
+features: [Intl.NumberFormat-v3]
+---*/
+
+function resolveUseGrouping(option) {
+ return new Intl.NumberFormat(undefined, { useGrouping: option }).resolvedOptions().useGrouping;
+}
+
+for (let string of ["min2", "auto", "always"]) {
+ assert.sameValue(resolveUseGrouping(string), string);
+}
+
+assert.sameValue(resolveUseGrouping(true), "always");
+assert.sameValue(resolveUseGrouping(false), false);
+assert.sameValue(resolveUseGrouping(undefined), "auto");
+assert.sameValue(resolveUseGrouping("true"), "auto");
+assert.sameValue(resolveUseGrouping("false"), "auto");
+
+for (let falsy of [0, null, ""]) {
+ assert.sameValue(resolveUseGrouping(falsy), false);
+}
+
+for (let invalidOptions of [42, "MIN2", {} , "True", "TRUE" , "FALSE" , "False" , "Undefined" , "undefined"]) {
+ assert.throws(RangeError, function () {
+ return new Intl.NumberFormat(undefined, { useGrouping: invalidOptions });
+ }, "Throws RangeError when useGrouping value is not supported");
+}
+
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/this-value-ignored.js b/js/src/tests/test262/intl402/NumberFormat/this-value-ignored.js
new file mode 100644
index 0000000000..ac07b22269
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/this-value-ignored.js
@@ -0,0 +1,37 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-intl-numberformat-constructor
+description: >
+ Tests that the this-value is ignored in NumberFormat, if the this-value
+ isn't a NumberFormat instance.
+author: Norbert Lindenberg
+includes: [testIntl.js]
+---*/
+
+testWithIntlConstructors(function (Constructor) {
+ if (Constructor === Intl.NumberFormat)
+ return;
+
+ var obj, newObj;
+
+ // variant 1: use constructor in a "new" expression
+ obj = new Constructor();
+ newObj = Intl.NumberFormat.call(obj);
+ assert.notSameValue(obj, newObj, "NumberFormat object created with \"new\" was not ignored as this-value.");
+
+ // variant 2: use constructor as a function
+ if (Constructor !== Intl.Collator &&
+ Constructor !== Intl.NumberFormat &&
+ Constructor !== Intl.DateTimeFormat)
+ {
+ // Newer Intl constructors are not callable as a function.
+ return;
+ }
+ obj = Constructor();
+ newObj = Intl.NumberFormat.call(obj);
+ assert.notSameValue(obj, newObj, "NumberFormat object created with constructor as function was not ignored as this-value.");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/throws-for-currency-style-without-currency-option.js b/js/src/tests/test262/intl402/NumberFormat/throws-for-currency-style-without-currency-option.js
new file mode 100644
index 0000000000..74d7d2934c
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/throws-for-currency-style-without-currency-option.js
@@ -0,0 +1,22 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es5id: 11.1.1_19
+description: >
+ Tests that the currency style can not be used without a specified
+ currency.
+author: Norbert Lindenberg
+---*/
+
+var defaultLocale = new Intl.NumberFormat().resolvedOptions().locale;
+
+assert.throws(TypeError, function () {
+ return new Intl.NumberFormat([defaultLocale], {style: "currency"});
+}, "Throws TypeError when currency code is not specified.");
+
+assert.throws(TypeError, function () {
+ return new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {style: "currency"});
+}, "Throws TypeError when currency code is not specified; Currenty code from Unicode locale extension sequence is ignored.");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/throws-for-maximumFractionDigits-over-limit.js b/js/src/tests/test262/intl402/NumberFormat/throws-for-maximumFractionDigits-over-limit.js
new file mode 100644
index 0000000000..0f2602bb3c
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/throws-for-maximumFractionDigits-over-limit.js
@@ -0,0 +1,24 @@
+// Copyright 2023 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: >
+ Tests that the options maximumFractionDigits limit to the range 0 - 100.
+info: |
+ InitializeNumberFormat ( numberFormat, locales, options )
+
+ 25.a.ii. Set mxfd to ? DefaultNumberOption(mxfd, 0, 100, undefined).
+
+ DefaultNumberOption ( value, minimum, maximum, fallback )
+
+ 3. If value is NaN or less than minimum or greater than maximum, throw a RangeError exception.
+---*/
+
+let wontThrow = new Intl.NumberFormat(undefined, {maximumFractionDigits: 100});
+
+assert.throws(RangeError, function () {
+ return new Intl.NumberFormat(undefined, {maximumFractionDigits: 101});
+}, "Throws RangeError when maximumFractionDigits is more than 100.");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/throws-for-maximumFractionDigits-under-limit.js b/js/src/tests/test262/intl402/NumberFormat/throws-for-maximumFractionDigits-under-limit.js
new file mode 100644
index 0000000000..446af0aeff
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/throws-for-maximumFractionDigits-under-limit.js
@@ -0,0 +1,24 @@
+// Copyright 2023 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: >
+ Tests that the options maximumFractionDigits limit to the range 0 - 100.
+info: |
+ InitializeNumberFormat ( numberFormat, locales, options )
+
+ 25.a.ii. Set mxfd to ? DefaultNumberOption(mxfd, 0, 100, undefined).
+
+ DefaultNumberOption ( value, minimum, maximum, fallback )
+
+ 3. If value is NaN or less than minimum or greater than maximum, throw a RangeError exception.
+---*/
+
+let wontThrow = new Intl.NumberFormat(undefined, {maximumFractionDigits: 0});
+
+assert.throws(RangeError, function () {
+ return new Intl.NumberFormat(undefined, {maximumFractionDigits: -1});
+}, "Throws RangeError when maximumFractionDigits is less than 0.");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/throws-for-minimumFractionDigits-over-limit.js b/js/src/tests/test262/intl402/NumberFormat/throws-for-minimumFractionDigits-over-limit.js
new file mode 100644
index 0000000000..699a67a1a7
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/throws-for-minimumFractionDigits-over-limit.js
@@ -0,0 +1,24 @@
+// Copyright 2023 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: >
+ Tests that the options minimumFractionDigits limit to the range 0 - 100.
+info: |
+ InitializeNumberFormat ( numberFormat, locales, options )
+
+ 25.a.ii. Set mxfd to ? DefaultNumberOption(mxfd, 0, 100, undefined).
+
+ DefaultNumberOption ( value, minimum, maximum, fallback )
+
+ 3. If value is NaN or less than minimum or greater than maximum, throw a RangeError exception.
+---*/
+
+let wontThrow = new Intl.NumberFormat(undefined, {minimumFractionDigits: 100});
+
+assert.throws(RangeError, function () {
+ return new Intl.NumberFormat(undefined, {minimumFractionDigits: 101});
+}, "Throws RangeError when minimumFractionDigits is more than 100.");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/intl402/NumberFormat/throws-for-minimumFractionDigits-under-limit.js b/js/src/tests/test262/intl402/NumberFormat/throws-for-minimumFractionDigits-under-limit.js
new file mode 100644
index 0000000000..d12e2502ed
--- /dev/null
+++ b/js/src/tests/test262/intl402/NumberFormat/throws-for-minimumFractionDigits-under-limit.js
@@ -0,0 +1,24 @@
+// Copyright 2023 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-initializenumberformat
+description: >
+ Tests that the options minimumFractionDigits limit to the range 0 - 100.
+info: |
+ InitializeNumberFormat ( numberFormat, locales, options )
+
+ 25.a.ii. Set mxfd to ? DefaultNumberOption(mxfd, 0, 100, undefined).
+
+ DefaultNumberOption ( value, minimum, maximum, fallback )
+
+ 3. If value is NaN or less than minimum or greater than maximum, throw a RangeError exception.
+---*/
+
+let wontThrow = new Intl.NumberFormat(undefined, {minimumFractionDigits: 0});
+
+assert.throws(RangeError, function () {
+ return new Intl.NumberFormat(undefined, {minimumFractionDigits: -1});
+}, "Throws RangeError when minimumFractionDigits is less than 0.");
+
+reportCompare(0, 0);