Commit d8fbe426 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[bigint] Adapt JSON.stringify.

Bug: v8:6791
Change-Id: Id34db2021c02b885be3f300648d5941362381d0b
Reviewed-on: https://chromium-review.googlesource.com/735561
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48896}
parent 3424c28b
......@@ -28,6 +28,7 @@
V(regexp_to_string, "[object RegExp]") \
V(string_to_string, "[object String]") \
V(bigint_string, "bigint") \
V(BigInt_string, "BigInt") \
V(bind_string, "bind") \
V(boolean_string, "boolean") \
V(Boolean_string, "Boolean") \
......
......@@ -187,11 +187,22 @@ bool JsonStringifier::InitializeGap(Handle<Object> gap) {
MaybeHandle<Object> JsonStringifier::ApplyToJsonFunction(Handle<Object> object,
Handle<Object> key) {
HandleScope scope(isolate_);
LookupIterator it(object, tojson_string_,
LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
Handle<Object> object_for_lookup = object;
if (object->IsBigInt()) {
ASSIGN_RETURN_ON_EXCEPTION(isolate_, object_for_lookup,
Object::ToObject(isolate_, object), Object);
}
DCHECK(object_for_lookup->IsJSReceiver());
// Retrieve toJSON function.
Handle<Object> fun;
ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object);
if (!fun->IsCallable()) return object;
{
LookupIterator it(object_for_lookup, tojson_string_,
LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object);
if (!fun->IsCallable()) return object;
}
// Call toJSON function.
if (key->IsSmi()) key = factory()->NumberToString(key);
......@@ -271,7 +282,7 @@ JsonStringifier::Result JsonStringifier::Serialize_(Handle<Object> object,
isolate_->stack_guard()->HandleInterrupts()->IsException(isolate_)) {
return EXCEPTION;
}
if (object->IsJSReceiver()) {
if (object->IsJSReceiver() || object->IsBigInt()) {
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate_, object, ApplyToJsonFunction(object, key), EXCEPTION);
}
......@@ -291,6 +302,10 @@ JsonStringifier::Result JsonStringifier::Serialize_(Handle<Object> object,
case MUTABLE_HEAP_NUMBER_TYPE:
if (deferred_string_key) SerializeDeferredKey(comma, key);
return SerializeHeapNumber(Handle<HeapNumber>::cast(object));
case BIGINT_TYPE:
isolate_->Throw(
*factory()->NewTypeError(MessageTemplate::kBigIntSerializeJSON));
return EXCEPTION;
case ODDBALL_TYPE:
switch (Oddball::cast(*object)->kind()) {
case Oddball::kFalse:
......@@ -350,6 +365,10 @@ JsonStringifier::Result JsonStringifier::SerializeJSValue(
EXCEPTION);
if (value->IsSmi()) return SerializeSmi(Smi::cast(*value));
SerializeHeapNumber(Handle<HeapNumber>::cast(value));
} else if (class_name == isolate_->heap()->BigInt_string()) {
isolate_->Throw(
*factory()->NewTypeError(MessageTemplate::kBigIntSerializeJSON));
return EXCEPTION;
} else if (class_name == isolate_->heap()->Boolean_string()) {
Object* value = JSValue::cast(*object)->value();
DCHECK(value->IsBoolean());
......
......@@ -275,6 +275,7 @@ class ErrorUtils : public AllStatic {
"The comparison function must be either a function or undefined") \
T(BigIntMixedTypes, \
"Cannot mix BigInt and other types, use explicit conversions") \
T(BigIntSerializeJSON, "Do not know how to serialize a BigInt") \
T(BigIntShr, "BigInts have no unsigned right shift, use >> instead") \
T(BigIntToNumber, "Cannot convert a BigInt value to a number") \
T(CalledNonCallable, "% is not a function") \
......
......@@ -428,7 +428,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(18),
B(LdaConstant), U8(16),
B(Star), R(19),
......
......@@ -143,7 +143,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(19),
B(LdaConstant), U8(13),
B(Star), R(20),
......@@ -432,7 +432,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(19),
B(LdaConstant), U8(13),
B(Star), R(20),
......@@ -743,7 +743,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(19),
B(LdaConstant), U8(13),
B(Star), R(20),
......@@ -991,7 +991,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(16),
B(LdaConstant), U8(10),
B(Star), R(17),
......
......@@ -86,7 +86,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(11),
B(LdaConstant), U8(8),
B(Star), R(12),
......@@ -227,7 +227,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(12),
B(LdaConstant), U8(8),
B(Star), R(13),
......@@ -380,7 +380,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(11),
B(LdaConstant), U8(8),
B(Star), R(12),
......@@ -523,7 +523,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(10),
B(LdaConstant), U8(10),
B(Star), R(11),
......
......@@ -90,7 +90,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(13),
B(LdaConstant), U8(7),
B(Star), R(14),
......@@ -268,7 +268,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(13),
B(LdaConstant), U8(11),
B(Star), R(14),
......@@ -422,7 +422,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(11),
B(LdaConstant), U8(9),
B(Star), R(12),
......@@ -524,7 +524,7 @@ bytecodes: [
B(JumpIfUndefined), U8(6),
B(Ldar), R(6),
B(JumpIfNotNull), U8(16),
B(LdaSmi), I8(68),
B(LdaSmi), I8(69),
B(Star), R(17),
B(LdaConstant), U8(4),
B(Star), R(18),
......@@ -580,7 +580,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(16),
B(LdaConstant), U8(9),
B(Star), R(17),
......@@ -754,7 +754,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(16),
B(LdaConstant), U8(10),
B(Star), R(17),
......@@ -953,7 +953,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(15),
B(LdaConstant), U8(14),
B(Star), R(16),
......@@ -1116,7 +1116,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(20),
B(LdaConstant), U8(7),
B(Star), R(21),
......@@ -1358,7 +1358,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(20),
B(LdaConstant), U8(9),
B(Star), R(21),
......
......@@ -257,7 +257,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(138),
B(Wide), B(LdaSmi), I16(139),
B(Star), R(14),
B(LdaConstant), U8(15),
B(Star), R(15),
......
......@@ -231,7 +231,7 @@ bytecodes: [
B(JumpIfUndefined), U8(6),
B(Ldar), R(3),
B(JumpIfNotNull), U8(16),
B(LdaSmi), I8(68),
B(LdaSmi), I8(69),
B(Star), R(4),
B(LdaConstant), U8(1),
B(Star), R(5),
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --harmony-bigint --no-opt
'use strict'
// Without .toJSON method.
assertEquals(undefined, BigInt.prototype.toJSON);
assertThrows(() => JSON.stringify(42n), TypeError);
assertThrows(() => JSON.stringify(Object(42n)), TypeError);
// With .toJSON method that returns a string.
BigInt.prototype.toJSON = function() {
assertEquals("bigint", typeof this);
return String(this);
}
assertEquals("\"42\"", JSON.stringify(42n));
BigInt.prototype.toJSON = function() {
assertEquals("object", typeof this);
return String(this);
}
assertEquals("\"42\"", JSON.stringify(Object(42n)));
// With .toJSON method that returns a BigInt primitive.
BigInt.prototype.toJSON = function() {return this};
assertThrows(() => JSON.stringify(42n), TypeError);
assertThrows(() => JSON.stringify(Object(42n)), TypeError);
// With .toJSON method that returns a BigInt object.
BigInt.prototype.toJSON = function() {return Object(this)};
assertThrows(() => JSON.stringify(42n), TypeError);
assertThrows(() => JSON.stringify(Object(42n)), TypeError);
// Without .toJSON method but with a replacer returning a string.
delete BigInt.prototype.toJSON;
let replacer;
replacer = function(k, v) {
assertEquals("bigint", typeof v);
assertTrue(42n == v);
return "43";
}
assertEquals("\"43\"", JSON.stringify(42n, replacer));
replacer = function(k, v) {
assertEquals("object", typeof v);
assertTrue(42n == v);
return "43";
}
assertEquals("\"43\"", JSON.stringify(Object(42n), replacer));
// Without .toJSON method but with a replacer returning a BigInt primitive.
assertEquals(undefined, BigInt.prototype.toJSON);
replacer = () => 43n;
assertThrows(() => JSON.stringify(42n, replacer), TypeError);
assertThrows(() => JSON.stringify(Object(42n), replacer), TypeError);
// Without .toJSON method but with a replacer returning a BigInt object.
assertEquals(undefined, BigInt.prototype.toJSON);
replacer = () => Object(43n);
assertThrows(() => JSON.stringify(42n, replacer), TypeError);
assertThrows(() => JSON.stringify(Object(42n), replacer), TypeError);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment