[bigint] Install Symbol.toStringTag and adapt O.p.toString.

Bug: v8:6791
Change-Id: I10bb316284ba3a0e326daad4f9b995f88d76c2a2
Reviewed-on: https://chromium-review.googlesource.com/739501
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48982}
This commit is contained in:
Georg Neis 2017-10-26 16:20:15 +02:00 committed by Commit Bot
parent 0b0bfc4bc3
commit 401b39b1dd
3 changed files with 60 additions and 10 deletions

View File

@ -4361,10 +4361,11 @@ void Genesis::InitializeGlobal_harmony_regexp_dotall() {
void Genesis::InitializeGlobal_harmony_bigint() {
if (!FLAG_harmony_bigint) return;
Factory* factory = isolate()->factory();
Handle<JSGlobalObject> global(native_context()->global_object());
Handle<JSFunction> bigint_fun = InstallFunction(
global, "BigInt", JS_VALUE_TYPE, JSValue::kSize, 0,
isolate()->factory()->the_hole_value(), Builtins::kBigIntConstructor);
Handle<JSFunction> bigint_fun =
InstallFunction(global, "BigInt", JS_VALUE_TYPE, JSValue::kSize, 0,
factory->the_hole_value(), Builtins::kBigIntConstructor);
bigint_fun->shared()->DontAdaptArguments();
bigint_fun->shared()->SetConstructStub(
*BUILTIN_CODE(isolate(), BigIntConstructor_ConstructStub));
@ -4400,6 +4401,10 @@ void Genesis::InitializeGlobal_harmony_bigint() {
// valueOf()
SimpleInstallFunction(prototype, "valueOf", Builtins::kBigIntPrototypeValueOf,
0, false);
// @@toStringTag
JSObject::AddProperty(prototype, factory->to_string_tag_symbol(),
factory->BigInt_string(),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
}
#ifdef V8_INTL_SUPPORT

View File

@ -303,7 +303,7 @@ TF_BUILTIN(ObjectPrototypeToString, ObjectBuiltinsAssembler) {
if_error(this), if_function(this), if_number(this, Label::kDeferred),
if_object(this), if_primitive(this), if_proxy(this, Label::kDeferred),
if_regexp(this), if_string(this), if_symbol(this, Label::kDeferred),
if_value(this);
if_value(this), if_bigint(this, Label::kDeferred);
Node* receiver = Parameter(Descriptor::kReceiver);
Node* context = Parameter(Descriptor::kContext);
@ -427,19 +427,19 @@ TF_BUILTIN(ObjectPrototypeToString, ObjectBuiltinsAssembler) {
BIND(&if_primitive);
{
Label return_null(this), return_undefined(this);
Label return_undefined(this);
GotoIf(IsStringInstanceType(receiver_instance_type), &if_string);
GotoIf(IsBigIntInstanceType(receiver_instance_type), &if_bigint);
GotoIf(IsBooleanMap(receiver_map), &if_boolean);
GotoIf(IsHeapNumberMap(receiver_map), &if_number);
GotoIf(IsSymbolMap(receiver_map), &if_symbol);
Branch(IsUndefined(receiver), &return_undefined, &return_null);
GotoIf(IsUndefined(receiver), &return_undefined);
CSA_ASSERT(this, IsNull(receiver));
Return(LoadRoot(Heap::knull_to_stringRootIndex));
BIND(&return_undefined);
Return(LoadRoot(Heap::kundefined_to_stringRootIndex));
BIND(&return_null);
Return(LoadRoot(Heap::knull_to_stringRootIndex));
}
BIND(&if_proxy);
@ -507,6 +507,20 @@ TF_BUILTIN(ObjectPrototypeToString, ObjectBuiltinsAssembler) {
Goto(&checkstringtag);
}
BIND(&if_bigint);
{
Node* native_context = LoadNativeContext(context);
Node* bigint_constructor =
LoadContextElement(native_context, Context::BIGINT_FUNCTION_INDEX);
Node* bigint_initial_map = LoadObjectField(
bigint_constructor, JSFunction::kPrototypeOrInitialMapOffset);
Node* bigint_prototype =
LoadObjectField(bigint_initial_map, Map::kPrototypeOffset);
var_default.Bind(LoadRoot(Heap::kobject_to_stringRootIndex));
var_holder.Bind(bigint_prototype);
Goto(&checkstringtag);
}
BIND(&if_value);
{
Node* receiver_value = LoadJSValueValue(receiver);
@ -514,7 +528,12 @@ TF_BUILTIN(ObjectPrototypeToString, ObjectBuiltinsAssembler) {
Node* receiver_value_map = LoadMap(receiver_value);
GotoIf(IsHeapNumberMap(receiver_value_map), &if_number);
GotoIf(IsBooleanMap(receiver_value_map), &if_boolean);
Branch(IsSymbolMap(receiver_value_map), &if_symbol, &if_string);
GotoIf(IsSymbolMap(receiver_value_map), &if_symbol);
Node* receiver_value_instance_type =
LoadMapInstanceType(receiver_value_map);
GotoIf(IsBigIntInstanceType(receiver_value_instance_type), &if_bigint);
CSA_ASSERT(this, IsStringInstanceType(receiver_value_instance_type));
Goto(&if_string);
}
BIND(&checkstringtag);

View File

@ -20,6 +20,32 @@ const six = BigInt(6);
assertSame(BigInt, BigInt.prototype.constructor)
}
// BigInt.prototype[Symbol.toStringTag]
{
const toStringTag = Object.getOwnPropertyDescriptor(
BigInt.prototype, Symbol.toStringTag);
assertTrue(toStringTag.configurable);
assertFalse(toStringTag.enumerable);
assertFalse(toStringTag.writable);
assertEquals("BigInt", toStringTag.value);
}
// Object.prototype.toString
{
const toString = Object.prototype.toString;
assertEquals("[object BigInt]", toString.call(42n));
assertEquals("[object BigInt]", toString.call(Object(42n)));
delete BigInt.prototype[Symbol.toStringTag];
assertEquals("[object Object]", toString.call(42n));
assertEquals("[object Object]", toString.call(Object(42n)));
BigInt.prototype[Symbol.toStringTag] = "foo";
assertEquals("[object foo]", toString.call(42n));
assertEquals("[object foo]", toString.call(Object(42n)));
}
// typeof
{
assertEquals(typeof zero, "bigint");