WebKit Bugzilla
Attachment 357129 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-20181213005045.patch (text/plain), 9.32 KB, created by
Yusuke Suzuki
on 2018-12-12 07:50:46 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Yusuke Suzuki
Created:
2018-12-12 07:50:46 PST
Size:
9.32 KB
patch
obsolete
>Subversion Revision: 239102 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 31522434d77a3ffa3b1ef47ca56d57c52db43d66..9784c2ad904ae15282e671c3a4bc110cf0c0b53c 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,20 @@ >+2018-12-12 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-11 Yusuke Suzuki <yusukesuzuki@slowstart.org> > > [BigInt] Simplify boolean context evaluation by leveraging JSString::offsetOfLength() == JSBigInt::offsetOfLength() >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/JSTests/ChangeLog b/JSTests/ChangeLog >index c6b86c9c26d5b33f88bf9cc998a05ced901d2265..3588b0ceeba6e3a20950be33086d67886875b270 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,19 @@ >+2018-12-12 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 Mark Lam <mark.lam@apple.com> > > PropertyAttribute needs a CustomValue bit. >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
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 192624
:
357129
|
357135
|
357137
|
357142
|
357143
|
357144
|
357216