Title: [239544] trunk
Revision
239544
Author
yusukesuz...@slowstart.org
Date
2018-12-23 02:09:09 -0800 (Sun, 23 Dec 2018)

Log Message

[BigInt] Support BigInt in JSON.stringify
https://bugs.webkit.org/show_bug.cgi?id=192624

Reviewed by Saam Barati.

JSTests:

* stress/big-int-json-stringify-to-json.js: Added.
(shouldBe):
(shouldThrow):
(BigInt.prototype.toJSON):
(shouldBe.JSON.stringify):
* stress/big-int-json-stringify.js: Added.
(shouldBe):
(shouldThrow):

Source/_javascript_Core:

This patch adds BigInt support to JSON.stringify, specified in [1].

[1]: https://tc39.github.io/proposal-bigint/#sec-serializejsonproperty

* runtime/JSONObject.cpp:
(JSC::unwrapBoxedPrimitive):
(JSC::Stringifier::toJSON):
(JSC::Stringifier::toJSONImpl):
(JSC::Stringifier::appendStringifiedValue):

LayoutTests:

The test is wrong according to the spec[1]. valueOf of Boolean object won't be called.

[1]: https://tc39.github.io/ecma262/#sec-serializejsonproperty

* js/resources/JSON-stringify.js:
* js/resources/json2-es5-compat.js:
(str):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (239543 => 239544)


--- trunk/JSTests/ChangeLog	2018-12-23 06:38:24 UTC (rev 239543)
+++ trunk/JSTests/ChangeLog	2018-12-23 10:09:09 UTC (rev 239544)
@@ -1,3 +1,19 @@
+2018-12-13  Yusuke Suzuki  <yusukesuz...@slowstart.org>
+
+        [BigInt] Support BigInt in JSON.stringify
+        https://bugs.webkit.org/show_bug.cgi?id=192624
+
+        Reviewed by Saam Barati.
+
+        * stress/big-int-json-stringify-to-json.js: Added.
+        (shouldBe):
+        (shouldThrow):
+        (BigInt.prototype.toJSON):
+        (shouldBe.JSON.stringify):
+        * stress/big-int-json-stringify.js: Added.
+        (shouldBe):
+        (shouldThrow):
+
 2018-12-20  Yusuke Suzuki  <yusukesuz...@slowstart.org>
 
         [JSC] Implement "well-formed JSON.stringify" proposal

Added: trunk/JSTests/stress/big-int-json-stringify-to-json.js (0 => 239544)


--- trunk/JSTests/stress/big-int-json-stringify-to-json.js	                        (rev 0)
+++ trunk/JSTests/stress/big-int-json-stringify-to-json.js	2018-12-23 10:09:09 UTC (rev 239544)
@@ -0,0 +1,50 @@
+//@ runBigIntEnabled
+
+function shouldBe(actual, expected)
+{
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+noInline(shouldBe);
+
+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+noInline(shouldThrow);
+
+var counter = 0;
+BigInt.prototype.toJSON = function () {
+    ++counter;
+    return Number(String(this));
+};
+
+shouldBe(JSON.stringify(0n), `0`);
+shouldBe(counter, 1);
+
+shouldBe(JSON.stringify([0n]), `[0]`);
+shouldBe(counter, 2);
+
+shouldBe(JSON.stringify({hello:0n}), `{"hello":0}`);
+shouldBe(counter, 3);
+
+var bigIntObject = Object(0n);
+
+shouldBe(JSON.stringify(bigIntObject), `0`);
+shouldBe(counter, 4);
+
+shouldBe(JSON.stringify([bigIntObject]), `[0]`);
+shouldBe(counter, 5);
+
+shouldBe(JSON.stringify({hello:bigIntObject}), `{"hello":0}`);
+shouldBe(counter, 6);

Added: trunk/JSTests/stress/big-int-json-stringify.js (0 => 239544)


--- trunk/JSTests/stress/big-int-json-stringify.js	                        (rev 0)
+++ trunk/JSTests/stress/big-int-json-stringify.js	2018-12-23 10:09:09 UTC (rev 239544)
@@ -0,0 +1,52 @@
+//@ runBigIntEnabled
+
+function shouldBe(actual, expected)
+{
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+noInline(shouldBe);
+
+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+noInline(shouldThrow);
+
+shouldThrow(() => {
+    JSON.stringify(0n);
+}, `TypeError: JSON.stringify cannot serialize BigInt.`);
+
+shouldThrow(() => {
+    JSON.stringify([0n]);
+}, `TypeError: JSON.stringify cannot serialize BigInt.`);
+
+shouldThrow(() => {
+    JSON.stringify({hello:0n});
+}, `TypeError: JSON.stringify cannot serialize BigInt.`);
+
+var bigIntObject = Object(0n);
+
+shouldThrow(() => {
+    JSON.stringify(bigIntObject);
+}, `TypeError: JSON.stringify cannot serialize BigInt.`);
+
+shouldThrow(() => {
+    JSON.stringify([bigIntObject]);
+}, `TypeError: JSON.stringify cannot serialize BigInt.`);
+
+shouldThrow(() => {
+    JSON.stringify({hello:bigIntObject});
+}, `TypeError: JSON.stringify cannot serialize BigInt.`);
+
+

Modified: trunk/LayoutTests/ChangeLog (239543 => 239544)


--- trunk/LayoutTests/ChangeLog	2018-12-23 06:38:24 UTC (rev 239543)
+++ trunk/LayoutTests/ChangeLog	2018-12-23 10:09:09 UTC (rev 239544)
@@ -1,3 +1,18 @@
+2018-12-13  Yusuke Suzuki  <yusukesuz...@slowstart.org>
+
+        [BigInt] Support BigInt in JSON.stringify
+        https://bugs.webkit.org/show_bug.cgi?id=192624
+
+        Reviewed by Saam Barati.
+
+        The test is wrong according to the spec[1]. valueOf of Boolean object won't be called.
+
+        [1]: https://tc39.github.io/ecma262/#sec-serializejsonproperty
+
+        * js/resources/JSON-stringify.js:
+        * js/resources/json2-es5-compat.js:
+        (str):
+
 2018-12-22  Wenson Hsieh  <wenson_hs...@apple.com>
 
         [iOS] Suppress native selection behaviors when focusing a very small editable element

Modified: trunk/LayoutTests/js/resources/JSON-stringify.js (239543 => 239544)


--- trunk/LayoutTests/js/resources/JSON-stringify.js	2018-12-23 06:38:24 UTC (rev 239543)
+++ trunk/LayoutTests/js/resources/JSON-stringify.js	2018-12-23 10:09:09 UTC (rev 239544)
@@ -69,7 +69,7 @@
         value.valueOf = function() { return 2; }
         return jsonObject.stringify(value);
     });
-    result[result.length - 1].expected = '2';
+    result[result.length - 1].expected = 'true';
     result.push(function(jsonObject){
         var value = new String("fail");
         value.toString = function() { return "converted string"; }

Modified: trunk/LayoutTests/js/resources/json2-es5-compat.js (239543 => 239544)


--- trunk/LayoutTests/js/resources/json2-es5-compat.js	2018-12-23 06:38:24 UTC (rev 239543)
+++ trunk/LayoutTests/js/resources/json2-es5-compat.js	2018-12-23 10:09:09 UTC (rev 239544)
@@ -267,8 +267,10 @@
 // What happens next depends on the value's type.
 
         if (value && ((typeof value) === "object")) {
-            if (value.constructor === String || value.constructor === Number || value.constructor === Boolean)
+            if (value.constructor === String || value.constructor === Number)
                 value = value.valueOf();
+            else if (value.constructor === Boolean)
+                value = Boolean.prototype.valueOf.call(value);
         }
 
         switch (typeof value) {

Modified: trunk/Source/_javascript_Core/ChangeLog (239543 => 239544)


--- trunk/Source/_javascript_Core/ChangeLog	2018-12-23 06:38:24 UTC (rev 239543)
+++ trunk/Source/_javascript_Core/ChangeLog	2018-12-23 10:09:09 UTC (rev 239544)
@@ -1,3 +1,20 @@
+2018-12-13  Yusuke Suzuki  <yusukesuz...@slowstart.org>
+
+        [BigInt] Support BigInt in JSON.stringify
+        https://bugs.webkit.org/show_bug.cgi?id=192624
+
+        Reviewed by Saam Barati.
+
+        This patch adds BigInt support to JSON.stringify, specified in [1].
+
+        [1]: https://tc39.github.io/proposal-bigint/#sec-serializejsonproperty
+
+        * runtime/JSONObject.cpp:
+        (JSC::unwrapBoxedPrimitive):
+        (JSC::Stringifier::toJSON):
+        (JSC::Stringifier::toJSONImpl):
+        (JSC::Stringifier::appendStringifiedValue):
+
 2018-12-21  Yusuke Suzuki  <yusukesuz...@slowstart.org>
 
         [JSC] Use appendUnbarriered for cached own keys

Modified: trunk/Source/_javascript_Core/runtime/JSONObject.cpp (239543 => 239544)


--- trunk/Source/_javascript_Core/runtime/JSONObject.cpp	2018-12-23 06:38:24 UTC (rev 239543)
+++ trunk/Source/_javascript_Core/runtime/JSONObject.cpp	2018-12-23 10:09:09 UTC (rev 239544)
@@ -27,6 +27,7 @@
 #include "JSONObject.h"
 
 #include "ArrayConstructor.h"
+#include "BigIntObject.h"
 #include "BooleanObject.h"
 #include "Error.h"
 #include "ExceptionHelpers.h"
@@ -110,8 +111,8 @@
 
     friend class Holder;
 
-    JSValue toJSON(JSObject*, const PropertyNameForFunctionCall&);
-    JSValue toJSONImpl(VM&, JSObject*, JSValue toJSONFunction, const PropertyNameForFunctionCall&);
+    JSValue toJSON(JSValue, const PropertyNameForFunctionCall&);
+    JSValue toJSONImpl(VM&, JSValue, JSValue toJSONFunction, const PropertyNameForFunctionCall&);
 
     enum StringifyResult { StringifyFailed, StringifySucceeded, StringifyFailedDueToUndefinedOrSymbolValue };
     StringifyResult appendStringifiedValue(StringBuilder&, JSValue, const Holder&, const PropertyNameForFunctionCall&);
@@ -148,8 +149,8 @@
         return jsNumber(object->toNumber(exec));
     if (object->inherits<StringObject>(vm))
         return object->toString(exec);
-    if (object->inherits<BooleanObject>(vm))
-        return object->toPrimitive(exec);
+    if (object->inherits<BooleanObject>(vm) || object->inherits<BigIntObject>(vm))
+        return jsCast<JSWrapperObject*>(object)->internalValue();
 
     // Do not unwrap SymbolObject to Symbol. It is not performed in the spec.
     // http://www.ecma-international.org/ecma-262/6.0/#sec-serializejsonproperty
@@ -286,34 +287,34 @@
     RELEASE_AND_RETURN(scope, jsString(m_exec, result.toString()));
 }
 
-ALWAYS_INLINE JSValue Stringifier::toJSON(JSObject* object, const PropertyNameForFunctionCall& propertyName)
+ALWAYS_INLINE JSValue Stringifier::toJSON(JSValue baseValue, const PropertyNameForFunctionCall& propertyName)
 {
     VM& vm = m_exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     scope.assertNoException();
 
-    PropertySlot slot(object, PropertySlot::InternalMethodType::Get);
-    bool hasProperty = object->getPropertySlot(m_exec, vm.propertyNames->toJSON, slot);
+    PropertySlot slot(baseValue, PropertySlot::InternalMethodType::Get);
+    bool hasProperty = baseValue.getPropertySlot(m_exec, vm.propertyNames->toJSON, slot);
     EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
     if (!hasProperty)
-        return object;
+        return baseValue;
 
     JSValue toJSONFunction = slot.getValue(m_exec, vm.propertyNames->toJSON);
     RETURN_IF_EXCEPTION(scope, { });
-    RELEASE_AND_RETURN(scope, toJSONImpl(vm, object, toJSONFunction, propertyName));
+    RELEASE_AND_RETURN(scope, toJSONImpl(vm, baseValue, toJSONFunction, propertyName));
 }
 
-JSValue Stringifier::toJSONImpl(VM& vm, JSObject* object, JSValue toJSONFunction, const PropertyNameForFunctionCall& propertyName)
+JSValue Stringifier::toJSONImpl(VM& vm, JSValue baseValue, JSValue toJSONFunction, const PropertyNameForFunctionCall& propertyName)
 {
     CallType callType;
     CallData callData;
     if (!toJSONFunction.isCallable(vm, callType, callData))
-        return object;
+        return baseValue;
 
     MarkedArgumentBuffer args;
     args.append(propertyName.value(m_exec));
     ASSERT(!args.hasOverflowed());
-    return call(m_exec, asObject(toJSONFunction), callType, callData, object, args);
+    return call(m_exec, asObject(toJSONFunction), callType, callData, baseValue, args);
 }
 
 Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& builder, JSValue value, const Holder& holder, const PropertyNameForFunctionCall& propertyName)
@@ -322,8 +323,8 @@
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     // Call the toJSON function.
-    if (value.isObject()) {
-        value = toJSON(asObject(value), propertyName);
+    if (value.isObject() || value.isBigInt()) {
+        value = toJSON(value, propertyName);
         RETURN_IF_EXCEPTION(scope, StringifyFailed);
     }
 
@@ -378,6 +379,11 @@
         return StringifySucceeded;
     }
 
+    if (value.isBigInt()) {
+        throwTypeError(m_exec, scope, "JSON.stringify cannot serialize BigInt."_s);
+        return StringifyFailed;
+    }
+
     if (!value.isObject())
         return StringifyFailed;
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to