<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[259919] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/259919">259919</a></dd>
<dt>Author</dt> <dd>ross.kirsling@sony.com</dd>
<dt>Date</dt> <dd>2020-04-10 20:59:50 -0700 (Fri, 10 Apr 2020)</dd>
</dl>

<h3>Log Message</h3>
<pre>[ECMA-402] Properly implement BigInt.prototype.toLocaleString
https://bugs.webkit.org/show_bug.cgi?id=209782

Reviewed by Darin Adler.

JSTests:

* stress/bigint-toLocaleString.js: Added.
* stress/intl-numberformat.js: Add test cases.
* test262/expectations.yaml: Mark 10 test cases as passing.

Source/JavaScriptCore:

Our BigInt's toLocaleString has been simply falling back to toString instead of following ECMA-402.
(https://tc39.es/ecma402/#sup-bigint.prototype.tolocalestring)

Since {Number, BigInt}.prototype.toLocaleString are internally the same as Intl.NumberFormat.prototype.format,
this patch simultaneously lets the latter method take a BigInt argument.
(https://tc39.es/ecma402/#sec-number-format-functions)

This patch continues to use the old unum_* API instead of ICU 62's new unumf_* API,
as the latter would require a large refactor as well as fallback paths.
(This will, however, be a prerequisite for https://bugs.webkit.org/show_bug.cgi?id=209774.)

* runtime/BigIntPrototype.cpp:
(JSC::bigIntProtoFuncToString):
(JSC::bigIntProtoFuncToLocaleString):
(JSC::bigIntProtoFuncToStringImpl): Deleted.
* runtime/IntlNumberFormat.cpp:
(JSC::IntlNumberFormat::format):
(JSC::IntlNumberFormat::formatNumber): Deleted.
* runtime/IntlNumberFormat.h:
* runtime/IntlNumberFormatPrototype.cpp:
(JSC::IntlNumberFormatFuncFormat):
(JSC::IntlNumberFormatPrototypeGetterFormat):
(JSC::IntlNumberFormatFuncFormatNumber): Deleted.
* runtime/NumberPrototype.cpp:
(JSC::numberProtoFuncToLocaleString):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestsstressintlnumberformatjs">trunk/JSTests/stress/intl-numberformat.js</a></li>
<li><a href="#trunkJSTeststest262expectationsyaml">trunk/JSTests/test262/expectations.yaml</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeBigIntPrototypecpp">trunk/Source/JavaScriptCore/runtime/BigIntPrototype.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeIntlNumberFormatcpp">trunk/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeIntlNumberFormath">trunk/Source/JavaScriptCore/runtime/IntlNumberFormat.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeIntlNumberFormatPrototypecpp">trunk/Source/JavaScriptCore/runtime/IntlNumberFormatPrototype.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeNumberPrototypecpp">trunk/Source/JavaScriptCore/runtime/NumberPrototype.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsstressbiginttoLocaleStringjs">trunk/JSTests/stress/bigint-toLocaleString.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (259918 => 259919)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog  2020-04-11 03:03:28 UTC (rev 259918)
+++ trunk/JSTests/ChangeLog     2020-04-11 03:59:50 UTC (rev 259919)
</span><span class="lines">@@ -1,5 +1,16 @@
</span><span class="cx"> 2020-04-10  Ross Kirsling  <ross.kirsling@sony.com>
</span><span class="cx"> 
</span><ins>+        [ECMA-402] Properly implement BigInt.prototype.toLocaleString
+        https://bugs.webkit.org/show_bug.cgi?id=209782
+
+        Reviewed by Darin Adler.
+
+        * stress/bigint-toLocaleString.js: Added.
+        * stress/intl-numberformat.js: Add test cases.
+        * test262/expectations.yaml: Mark 10 test cases as passing.
+
+2020-04-10  Ross Kirsling  <ross.kirsling@sony.com>
+
</ins><span class="cx">         Unreviewed gardening for JSTests/stress. Remove skips that were forgotten in r259658.
</span><span class="cx"> 
</span><span class="cx">         * stress/array-toLocaleString.js:
</span></span></pre></div>
<a id="trunkJSTestsstressbiginttoLocaleStringjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/bigint-toLocaleString.js (0 => 259919)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/bigint-toLocaleString.js                            (rev 0)
+++ trunk/JSTests/stress/bigint-toLocaleString.js       2020-04-11 03:59:50 UTC (rev 259919)
</span><span class="lines">@@ -0,0 +1,51 @@
</span><ins>+//@ runBigIntEnabled
+
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error(`expected ${expected} but got ${actual}`);
+}
+
+function shouldNotThrow(func) {
+  func();
+}
+
+function shouldThrow(func, errorType) {
+    let error;
+    try {
+        func();
+    } catch (e) {
+        error = e;
+    }
+
+    if (!(error instanceof errorType))
+        throw new Error(`Expected ${errorType.name}!`);
+}
+
+shouldBe(BigInt.prototype.toLocaleString.length, 0);
+shouldBe(Object.getOwnPropertyDescriptor(BigInt.prototype, 'toLocaleString').enumerable, false);
+shouldBe(Object.getOwnPropertyDescriptor(BigInt.prototype, 'toLocaleString').configurable, true);
+shouldBe(Object.getOwnPropertyDescriptor(BigInt.prototype, 'toLocaleString').writable, true);
+
+// Test thisBigIntValue abrupt completion.
+shouldNotThrow(() => BigInt.prototype.toLocaleString.call(0n));
+shouldNotThrow(() => BigInt.prototype.toLocaleString.call(BigInt(0)));
+shouldThrow(() => BigInt.prototype.toLocaleString.call(), TypeError);
+shouldThrow(() => BigInt.prototype.toLocaleString.call(undefined), TypeError);
+shouldThrow(() => BigInt.prototype.toLocaleString.call(null), TypeError);
+shouldThrow(() => BigInt.prototype.toLocaleString.call(1), TypeError);
+shouldThrow(() => BigInt.prototype.toLocaleString.call('1'), TypeError);
+shouldThrow(() => BigInt.prototype.toLocaleString.call([]), TypeError);
+shouldThrow(() => BigInt.prototype.toLocaleString.call(Symbol()), TypeError);
+
+shouldBe(0n.toLocaleString(), '0');
+shouldBe(BigInt(1).toLocaleString(), '1');
+
+// Test for NumberFormat behavior.
+shouldThrow(() => 0n.toLocaleString('i'), RangeError);
+
+// Test that locale parameter is passed through properly.
+shouldBe(123456789n.toLocaleString('ar'), '١٢٣٬٤٥٦٬٧٨٩');
+shouldBe(123456789n.toLocaleString('zh-Hans-CN-u-nu-hanidec'), '一二三,四五六,七八九');
+
+// Test that options parameter is passed through properly.
+shouldBe(123456n.toLocaleString('en', { maximumSignificantDigits: 3 }), '123,000');
</ins></span></pre></div>
<a id="trunkJSTestsstressintlnumberformatjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/stress/intl-numberformat.js (259918 => 259919)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/intl-numberformat.js        2020-04-11 03:03:28 UTC (rev 259918)
+++ trunk/JSTests/stress/intl-numberformat.js   2020-04-11 03:59:50 UTC (rev 259919)
</span><span class="lines">@@ -1,3 +1,5 @@
</span><ins>+//@ runBigIntEnabled
+
</ins><span class="cx"> function shouldBe(actual, expected) {
</span><span class="cx">     if (actual !== expected)
</span><span class="cx">         throw new Error(`expected ${expected} but got ${actual}`);
</span><span class="lines">@@ -439,3 +441,10 @@
</span><span class="cx">     shouldBe(Intl.NumberFormat.call(legacy, 'en-u-nu-arab').format(1.2345), '١٫٢٣٥');
</span><span class="cx">     shouldBe(Intl.NumberFormat.apply(incompat) !== incompat, true);
</span><span class="cx"> }
</span><ins>+
+// BigInt tests
+shouldBe(Intl.NumberFormat().format(0n), '0');
+shouldBe(Intl.NumberFormat().format(BigInt(1)), '1');
+shouldBe(Intl.NumberFormat('ar').format(123456789n), '١٢٣٬٤٥٦٬٧٨٩');
+shouldBe(Intl.NumberFormat('zh-Hans-CN-u-nu-hanidec').format(123456789n), '一二三,四五六,七八九');
+shouldBe(Intl.NumberFormat('en', { maximumSignificantDigits: 3 }).format(123456n), '123,000');
</ins></span></pre></div>
<a id="trunkJSTeststest262expectationsyaml"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/test262/expectations.yaml (259918 => 259919)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/test262/expectations.yaml  2020-04-11 03:03:28 UTC (rev 259918)
+++ trunk/JSTests/test262/expectations.yaml     2020-04-11 03:59:50 UTC (rev 259919)
</span><span class="lines">@@ -1911,21 +1911,6 @@
</span><span class="cx"> test/built-ins/WeakSet/proto-from-ctor-realm.js:
</span><span class="cx">   default: 'Test262Error: Expected SameValue(«[object WeakSet]», «[object WeakSet]») to be true'
</span><span class="cx">   strict mode: 'Test262Error: Expected SameValue(«[object WeakSet]», «[object WeakSet]») to be true'
</span><del>-test/intl402/BigInt/prototype/toLocaleString/de-DE.js:
-  default: 'RangeError: toString() radix argument must be between 2 and 36'
-  strict mode: 'RangeError: toString() radix argument must be between 2 and 36'
-test/intl402/BigInt/prototype/toLocaleString/default-options-object-prototype.js:
-  default: 'RangeError: toString() radix argument must be between 2 and 36'
-  strict mode: 'RangeError: toString() radix argument must be between 2 and 36'
-test/intl402/BigInt/prototype/toLocaleString/en-US.js:
-  default: 'RangeError: toString() radix argument must be between 2 and 36'
-  strict mode: 'RangeError: toString() radix argument must be between 2 and 36'
-test/intl402/BigInt/prototype/toLocaleString/returns-same-results-as-NumberFormat.js:
-  default: "TypeError: Conversion from 'BigInt' to 'number' is not allowed."
-  strict mode: "TypeError: Conversion from 'BigInt' to 'number' is not allowed."
-test/intl402/BigInt/prototype/toLocaleString/throws-same-exceptions-as-NumberFormat.js:
-  default: "Test262Error: BigInt.prototype.toLocaleString didn't throw exception for locales null. Expected a TypeError but got a RangeError"
-  strict mode: "Test262Error: BigInt.prototype.toLocaleString didn't throw exception for locales null. Expected a TypeError but got a RangeError"
</del><span class="cx"> test/intl402/Collator/missing-unicode-ext-value-defaults-to-true.js:
</span><span class="cx">   default: 'Test262Error: "kn" should be returned in locale. Expected SameValue(«false», «true») to be true'
</span><span class="cx">   strict mode: 'Test262Error: "kn" should be returned in locale. Expected SameValue(«false», «true») to be true'
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (259918 => 259919)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2020-04-11 03:03:28 UTC (rev 259918)
+++ trunk/Source/JavaScriptCore/ChangeLog       2020-04-11 03:59:50 UTC (rev 259919)
</span><span class="lines">@@ -1,3 +1,36 @@
</span><ins>+2020-04-10  Ross Kirsling  <ross.kirsling@sony.com>
+
+        [ECMA-402] Properly implement BigInt.prototype.toLocaleString
+        https://bugs.webkit.org/show_bug.cgi?id=209782
+
+        Reviewed by Darin Adler.
+
+        Our BigInt's toLocaleString has been simply falling back to toString instead of following ECMA-402.
+        (https://tc39.es/ecma402/#sup-bigint.prototype.tolocalestring)
+
+        Since {Number, BigInt}.prototype.toLocaleString are internally the same as Intl.NumberFormat.prototype.format,
+        this patch simultaneously lets the latter method take a BigInt argument.
+        (https://tc39.es/ecma402/#sec-number-format-functions)
+
+        This patch continues to use the old unum_* API instead of ICU 62's new unumf_* API,
+        as the latter would require a large refactor as well as fallback paths.
+        (This will, however, be a prerequisite for https://bugs.webkit.org/show_bug.cgi?id=209774.)
+
+        * runtime/BigIntPrototype.cpp:
+        (JSC::bigIntProtoFuncToString):
+        (JSC::bigIntProtoFuncToLocaleString):
+        (JSC::bigIntProtoFuncToStringImpl): Deleted.
+        * runtime/IntlNumberFormat.cpp:
+        (JSC::IntlNumberFormat::format):
+        (JSC::IntlNumberFormat::formatNumber): Deleted.
+        * runtime/IntlNumberFormat.h:
+        * runtime/IntlNumberFormatPrototype.cpp:
+        (JSC::IntlNumberFormatFuncFormat):
+        (JSC::IntlNumberFormatPrototypeGetterFormat):
+        (JSC::IntlNumberFormatFuncFormatNumber): Deleted.
+        * runtime/NumberPrototype.cpp:
+        (JSC::numberProtoFuncToLocaleString):
+
</ins><span class="cx"> 2020-04-10  Devin Rousso  <drousso@apple.com>
</span><span class="cx"> 
</span><span class="cx">         The rhs in `ReadModifyResolveNode` should be evaluated before throwing an exception if the lhs is read-only
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeBigIntPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/BigIntPrototype.cpp (259918 => 259919)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/BigIntPrototype.cpp  2020-04-11 03:03:28 UTC (rev 259918)
+++ trunk/Source/JavaScriptCore/runtime/BigIntPrototype.cpp     2020-04-11 03:59:50 UTC (rev 259919)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> #include "BigIntObject.h"
</span><span class="cx"> #include "Error.h"
</span><span class="cx"> #include "IntegrityInlines.h"
</span><ins>+#include "IntlNumberFormat.h"
</ins><span class="cx"> #include "JSBigInt.h"
</span><span class="cx"> #include "JSCBuiltins.h"
</span><span class="cx"> #include "JSCInlines.h"
</span><span class="lines">@@ -91,7 +92,7 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static JSValue bigIntProtoFuncToStringImpl(JSGlobalObject* globalObject, CallFrame* callFrame)
</del><ins>+EncodedJSValue JSC_HOST_CALL bigIntProtoFuncToString(JSGlobalObject* globalObject, CallFrame* callFrame)
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="lines">@@ -98,7 +99,7 @@
</span><span class="cx"> 
</span><span class="cx">     JSBigInt* value = toThisBigIntValue(vm, callFrame->thisValue());
</span><span class="cx">     if (!value)
</span><del>-        return throwTypeError(globalObject, scope, "'this' value must be a BigInt or BigIntObject"_s);
</del><ins>+        return throwVMTypeError(globalObject, scope, "'this' value must be a BigInt or BigIntObject"_s);
</ins><span class="cx"> 
</span><span class="cx">     ASSERT(value);
</span><span class="cx"> 
</span><span class="lines">@@ -110,19 +111,24 @@
</span><span class="cx">     RETURN_IF_EXCEPTION(scope, { });
</span><span class="cx">     scope.release();
</span><span class="cx">     if (resultString.length() == 1)
</span><del>-        return vm.smallStrings.singleCharacterString(resultString[0]);
</del><ins>+        return JSValue::encode(vm.smallStrings.singleCharacterString(resultString[0]));
</ins><span class="cx"> 
</span><del>-    return jsNontrivialString(vm, resultString);
</del><ins>+    return JSValue::encode(jsNontrivialString(vm, resultString));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-EncodedJSValue JSC_HOST_CALL bigIntProtoFuncToString(JSGlobalObject* globalObject, CallFrame* callFrame)
</del><ins>+EncodedJSValue JSC_HOST_CALL bigIntProtoFuncToLocaleString(JSGlobalObject* globalObject, CallFrame* callFrame)
</ins><span class="cx"> {
</span><del>-    return JSValue::encode(bigIntProtoFuncToStringImpl(globalObject, callFrame));
-}
</del><ins>+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
</ins><span class="cx"> 
</span><del>-EncodedJSValue JSC_HOST_CALL bigIntProtoFuncToLocaleString(JSGlobalObject* globalObject, CallFrame* callFrame)
-{
-    return JSValue::encode(bigIntProtoFuncToStringImpl(globalObject, callFrame));
</del><ins>+    JSBigInt* value = toThisBigIntValue(vm, callFrame->thisValue());
+    if (!value)
+        return throwVMTypeError(globalObject, scope, "'this' value must be a BigInt or BigIntObject"_s);
+
+    auto* numberFormat = IntlNumberFormat::create(vm, globalObject->numberFormatStructure());
+    numberFormat->initializeNumberFormat(globalObject, callFrame->argument(0), callFrame->argument(1));
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->format(globalObject, value)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL bigIntProtoFuncValueOf(JSGlobalObject* globalObject, CallFrame* callFrame)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeIntlNumberFormatcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp (259918 => 259919)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp 2020-04-11 03:03:28 UTC (rev 259918)
+++ trunk/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp    2020-04-11 03:59:50 UTC (rev 259919)
</span><span class="lines">@@ -330,29 +330,57 @@
</span><span class="cx">     m_initializedNumberFormat = true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSValue IntlNumberFormat::formatNumber(JSGlobalObject* globalObject, double number)
</del><ins>+// https://tc39.es/ecma402/#sec-formatnumber
+JSValue IntlNumberFormat::format(JSGlobalObject* globalObject, double value)
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="cx"> 
</span><del>-    // 11.3.4 FormatNumber abstract operation (ECMA-402 2.0)
</del><span class="cx">     if (!m_initializedNumberFormat)
</span><span class="cx">         return throwTypeError(globalObject, scope, "Intl.NumberFormat.prototype.format called on value that's not an object initialized as a NumberFormat"_s);
</span><span class="cx"> 
</span><span class="cx">     UErrorCode status = U_ZERO_ERROR;
</span><span class="cx">     Vector<UChar, 32> buffer(32);
</span><del>-    auto length = unum_formatDouble(m_numberFormat.get(), number, buffer.data(), buffer.size(), nullptr, &status);
</del><ins>+    auto length = unum_formatDouble(m_numberFormat.get(), value, buffer.data(), buffer.size(), nullptr, &status);
</ins><span class="cx">     if (status == U_BUFFER_OVERFLOW_ERROR) {
</span><span class="cx">         buffer.grow(length);
</span><span class="cx">         status = U_ZERO_ERROR;
</span><del>-        unum_formatDouble(m_numberFormat.get(), number, buffer.data(), length, nullptr, &status);
</del><ins>+        unum_formatDouble(m_numberFormat.get(), value, buffer.data(), length, nullptr, &status);
</ins><span class="cx">     }
</span><span class="cx">     if (U_FAILURE(status))
</span><del>-        return throwException(globalObject, scope, createError(globalObject, "Failed to format a number."_s));
</del><ins>+        return throwTypeError(globalObject, scope, "Failed to format a number."_s);
</ins><span class="cx"> 
</span><span class="cx">     return jsString(vm, String(buffer.data(), length));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JSValue IntlNumberFormat::format(JSGlobalObject* globalObject, JSBigInt* value)
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    if (!m_initializedNumberFormat)
+        return throwTypeError(globalObject, scope, "Intl.NumberFormat.prototype.format called on value that's not an object initialized as a NumberFormat"_s);
+
+    auto string = value->toString(globalObject, 10);
+    RETURN_IF_EXCEPTION(scope, { });
+
+    ASSERT(string.is8Bit() && string.isAllASCII());
+    auto* rawString = reinterpret_cast<const char*>(string.characters8());
+
+    UErrorCode status = U_ZERO_ERROR;
+    Vector<UChar, 32> buffer(32);
+    auto length = unum_formatDecimal(m_numberFormat.get(), rawString, string.length(), buffer.data(), buffer.size(), nullptr, &status);
+    if (status == U_BUFFER_OVERFLOW_ERROR) {
+        buffer.grow(length);
+        status = U_ZERO_ERROR;
+        unum_formatDecimal(m_numberFormat.get(), rawString, string.length(), buffer.data(), length, nullptr, &status);
+    }
+    if (U_FAILURE(status))
+        return throwTypeError(globalObject, scope, "Failed to format a BigInt."_s);
+
+    return jsString(vm, String(buffer.data(), length));
+}
+
</ins><span class="cx"> ASCIILiteral IntlNumberFormat::styleString(Style style)
</span><span class="cx"> {
</span><span class="cx">     switch (style) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeIntlNumberFormath"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/IntlNumberFormat.h (259918 => 259919)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/IntlNumberFormat.h   2020-04-11 03:03:28 UTC (rev 259918)
+++ trunk/Source/JavaScriptCore/runtime/IntlNumberFormat.h      2020-04-11 03:59:50 UTC (rev 259919)
</span><span class="lines">@@ -57,7 +57,8 @@
</span><span class="cx">     DECLARE_INFO;
</span><span class="cx"> 
</span><span class="cx">     void initializeNumberFormat(JSGlobalObject*, JSValue locales, JSValue optionsValue);
</span><del>-    JSValue formatNumber(JSGlobalObject*, double number);
</del><ins>+    JSValue format(JSGlobalObject*, double);
+    JSValue format(JSGlobalObject*, JSBigInt*);
</ins><span class="cx">     JSValue formatToParts(JSGlobalObject*, double value);
</span><span class="cx">     JSObject* resolvedOptions(JSGlobalObject*);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeIntlNumberFormatPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/IntlNumberFormatPrototype.cpp (259918 => 259919)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/IntlNumberFormatPrototype.cpp        2020-04-11 03:03:28 UTC (rev 259918)
+++ trunk/Source/JavaScriptCore/runtime/IntlNumberFormatPrototype.cpp   2020-04-11 03:59:50 UTC (rev 259919)
</span><span class="lines">@@ -80,23 +80,19 @@
</span><span class="cx">     putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsNontrivialString(vm, "Object"_s), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static EncodedJSValue JSC_HOST_CALL IntlNumberFormatFuncFormatNumber(JSGlobalObject* globalObject, CallFrame* callFrame)
</del><ins>+// https://tc39.es/ecma402/#sec-number-format-functions
+static EncodedJSValue JSC_HOST_CALL IntlNumberFormatFuncFormat(JSGlobalObject* globalObject, CallFrame* callFrame)
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><del>-    // 11.3.4 Format Number Functions (ECMA-402 2.0)
-    // 1. Let nf be the this value.
-    // 2. Assert: Type(nf) is Object and nf has an [[initializedNumberFormat]] internal slot whose value  true.
-    IntlNumberFormat* numberFormat = jsCast<IntlNumberFormat*>(callFrame->thisValue());
</del><ins>+    auto* numberFormat = jsCast<IntlNumberFormat*>(callFrame->thisValue());
</ins><span class="cx"> 
</span><del>-    // 3. If value is not provided, let value be undefined.
-    // 4. Let x be ToNumber(value).
-    double number = callFrame->argument(0).toNumber(globalObject);
-    // 5. ReturnIfAbrupt(x).
</del><ins>+    auto variant = callFrame->argument(0).toNumeric(globalObject);
</ins><span class="cx">     RETURN_IF_EXCEPTION(scope, encodedJSValue());
</span><span class="cx"> 
</span><del>-    // 6. Return FormatNumber(nf, x).
-    RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->formatNumber(globalObject, number)));
</del><ins>+    RELEASE_AND_RETURN(scope, JSValue::encode(switchOn(variant, [&](auto&& value) {
+        return numberFormat->format(globalObject, value);
+    })));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL IntlNumberFormatPrototypeGetterFormat(JSGlobalObject* globalObject, CallFrame* callFrame)
</span><span class="lines">@@ -125,7 +121,7 @@
</span><span class="cx">         JSGlobalObject* globalObject = nf->globalObject(vm);
</span><span class="cx">         // a. Let F be a new built-in function object as defined in 11.3.4.
</span><span class="cx">         // b. The value of F’s length property is 1.
</span><del>-        JSFunction* targetObject = JSFunction::create(vm, globalObject, 1, "format"_s, IntlNumberFormatFuncFormatNumber, NoIntrinsic);
</del><ins>+        auto* targetObject = JSFunction::create(vm, globalObject, 1, "format"_s, IntlNumberFormatFuncFormat, NoIntrinsic);
</ins><span class="cx">         // c. Let bf be BoundFunctionCreate(F, «this value»).
</span><span class="cx">         boundFormat = JSBoundFunction::create(vm, globalObject, targetObject, nf, nullptr, 1, nullptr);
</span><span class="cx">         RETURN_IF_EXCEPTION(scope, encodedJSValue());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeNumberPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/NumberPrototype.cpp (259918 => 259919)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/NumberPrototype.cpp  2020-04-11 03:03:28 UTC (rev 259918)
+++ trunk/Source/JavaScriptCore/runtime/NumberPrototype.cpp     2020-04-11 03:59:50 UTC (rev 259919)
</span><span class="lines">@@ -578,10 +578,10 @@
</span><span class="cx">     if (!toThisNumber(vm, callFrame->thisValue(), x))
</span><span class="cx">         return throwVMToThisNumberError(globalObject, scope, callFrame->thisValue());
</span><span class="cx"> 
</span><del>-    IntlNumberFormat* numberFormat = IntlNumberFormat::create(vm, globalObject->numberFormatStructure());
</del><ins>+    auto* numberFormat = IntlNumberFormat::create(vm, globalObject->numberFormatStructure());
</ins><span class="cx">     numberFormat->initializeNumberFormat(globalObject, callFrame->argument(0), callFrame->argument(1));
</span><span class="cx">     RETURN_IF_EXCEPTION(scope, encodedJSValue());
</span><del>-    RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->formatNumber(globalObject, x)));
</del><ins>+    RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->format(globalObject, x)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL numberProtoFuncValueOf(JSGlobalObject* globalObject, CallFrame* callFrame)
</span></span></pre>
</div>
</div>

</body>
</html>