WebKit Bugzilla
Attachment 357216 Details for
Bug 192624
: [BigInt] Support BigInt in JSON.stringify
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-192624-20181213173215.patch (text/plain), 11.61 KB, created by
Yusuke Suzuki
on 2018-12-13 00:32:16 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Yusuke Suzuki
Created:
2018-12-13 00:32:16 PST
Size:
11.61 KB
patch
obsolete
>Subversion Revision: 239154 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 768a9b529d233873720e9c658a6e8cd1cef479f1..fccfc52198f198ebb0a9f903e652d336441d57bb 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,20 @@ >+2018-12-13 Yusuke Suzuki <yusukesuzuki@slowstart.org> >+ >+ [BigInt] Support BigInt in JSON.stringify >+ https://bugs.webkit.org/show_bug.cgi?id=192624 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ 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-13 Yusuke Suzuki <yusukesuzuki@slowstart.org> > > Unreviewed, build fix after r239153 >diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp >index 779fe64d3789e33b79ceedc6498943e82b05563b..c46ac0855b21943a3957826d9fa6432f8cf2a580 100644 >--- a/Source/JavaScriptCore/runtime/JSONObject.cpp >+++ b/Source/JavaScriptCore/runtime/JSONObject.cpp >@@ -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 @@ class Stringifier { > > 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 @@ static inline JSValue unwrapBoxedPrimitive(ExecState* exec, JSValue value) > 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 >@@ -283,34 +284,34 @@ JSValue Stringifier::stringify(JSValue value) > 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) >@@ -319,8 +320,8 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& > 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); > } > >@@ -379,6 +380,11 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& > return StringifySucceeded; > } > >+ if (value.isBigInt()) { >+ throwTypeError(m_exec, scope, "JSON.stringify cannot serialize BigInt."_s); >+ return StringifyFailed; >+ } >+ > if (!value.isObject()) > return StringifyFailed; > >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 881cbfbf0fe49ac3ef6f7888a9508b7d3756e2ab..208b77759026bcf51b7e0ae9ed0d2af8150572ff 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,18 @@ >+2018-12-13 Yusuke Suzuki <yusukesuzuki@slowstart.org> >+ >+ [BigInt] Support BigInt in JSON.stringify >+ https://bugs.webkit.org/show_bug.cgi?id=192624 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ 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-12 Simon Fraser <simon.fraser@apple.com> > > REGRESSION (r238090): CAPCHA UI jumps to the wrong location >diff --git a/LayoutTests/js/resources/JSON-stringify.js b/LayoutTests/js/resources/JSON-stringify.js >index 30242b4838bc5b2d7ff798487b8eeb8113aecc7b..509e4e4c5b1b2ffa872665b7f432951570456b57 100644 >--- a/LayoutTests/js/resources/JSON-stringify.js >+++ b/LayoutTests/js/resources/JSON-stringify.js >@@ -69,7 +69,7 @@ function createTests() { > 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"; } >diff --git a/LayoutTests/js/resources/json2-es5-compat.js b/LayoutTests/js/resources/json2-es5-compat.js >index 047b3d490878485a328e9c870682fe288d98b892..a29229a22e3c95ddc0978dfc7be2eb789ee91411 100644 >--- a/LayoutTests/js/resources/json2-es5-compat.js >+++ b/LayoutTests/js/resources/json2-es5-compat.js >@@ -244,8 +244,10 @@ function str(key, holder) { > // 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) { >diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog >index c18385754065aa9f1fb7a407334695aff839f4c9..09c47dcbc88e47d78cd6166a2c1523179e1e1c4e 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,19 @@ >+2018-12-13 Yusuke Suzuki <yusukesuzuki@slowstart.org> >+ >+ [BigInt] Support BigInt in JSON.stringify >+ https://bugs.webkit.org/show_bug.cgi?id=192624 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * 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-10 Yusuke Suzuki <yusukesuzuki@slowstart.org> > > [JSC] Optimize Object.keys by caching own keys results in StructureRareData >diff --git a/JSTests/stress/big-int-json-stringify-to-json.js b/JSTests/stress/big-int-json-stringify-to-json.js >new file mode 100644 >index 0000000000000000000000000000000000000000..e5c25a3460430e1364780a45bfc6ba16ec8ac755 >--- /dev/null >+++ b/JSTests/stress/big-int-json-stringify-to-json.js >@@ -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); >diff --git a/JSTests/stress/big-int-json-stringify.js b/JSTests/stress/big-int-json-stringify.js >new file mode 100644 >index 0000000000000000000000000000000000000000..39eb806c9bac9b722442259ef5672a11165eb1ea >--- /dev/null >+++ b/JSTests/stress/big-int-json-stringify.js >@@ -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.`); >+ >+
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
saam
:
review+
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 192624
:
357129
|
357135
|
357137
|
357142
|
357143
|
357144
| 357216