| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 38deeb825d4b291c707d5e76c1f3cffbf4f1b94a..adf6c270d8382fc643d7e282b3c73022f50d9cf4 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -219,6 +219,154 @@ MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) {
|
| }
|
| }
|
|
|
| +namespace {
|
| +
|
| +bool IsErrorObject(Isolate* isolate, Handle<Object> object) {
|
| + if (!object->IsJSReceiver()) return false;
|
| + Handle<Symbol> symbol = isolate->factory()->stack_trace_symbol();
|
| + return JSReceiver::HasOwnProperty(Handle<JSReceiver>::cast(object), symbol)
|
| + .FromMaybe(false);
|
| +}
|
| +
|
| +Handle<String> NoSideEffectsErrorToString(Isolate* isolate,
|
| + Handle<Object> input) {
|
| + Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
|
| +
|
| + Handle<Name> name_key = isolate->factory()->name_string();
|
| + Handle<Object> name = JSReceiver::GetDataProperty(receiver, name_key);
|
| + Handle<String> name_str = (name->IsUndefined(isolate))
|
| + ? isolate->factory()->Error_string()
|
| + : Object::NoSideEffectsToString(isolate, name);
|
| +
|
| + Handle<Name> msg_key = isolate->factory()->message_string();
|
| + Handle<Object> msg = JSReceiver::GetDataProperty(receiver, msg_key);
|
| + Handle<String> msg_str = (msg->IsUndefined(isolate))
|
| + ? isolate->factory()->empty_string()
|
| + : Object::NoSideEffectsToString(isolate, msg);
|
| +
|
| + if (name_str->length() == 0) return msg_str;
|
| + if (msg_str->length() == 0) return name_str;
|
| +
|
| + IncrementalStringBuilder builder(isolate);
|
| + builder.AppendString(name_str);
|
| + builder.AppendCString(": ");
|
| + builder.AppendString(msg_str);
|
| +
|
| + return builder.Finish().ToHandleChecked();
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// static
|
| +Handle<String> Object::NoSideEffectsToString(Isolate* isolate,
|
| + Handle<Object> input) {
|
| + DisallowJavascriptExecution no_js(isolate);
|
| +
|
| + if (input->IsString() || input->IsNumber() || input->IsOddball() ||
|
| + input->IsSimd128Value()) {
|
| + return Object::ToString(isolate, input).ToHandleChecked();
|
| + } else if (input->IsFunction()) {
|
| + // -- F u n c t i o n
|
| + Handle<String> fun_str;
|
| + if (input->IsJSBoundFunction()) {
|
| + fun_str = JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(input));
|
| + } else {
|
| + DCHECK(input->IsJSFunction());
|
| + fun_str = JSFunction::ToString(Handle<JSFunction>::cast(input));
|
| + }
|
| +
|
| + if (fun_str->length() > 128) {
|
| + IncrementalStringBuilder builder(isolate);
|
| + builder.AppendString(isolate->factory()->NewSubString(fun_str, 0, 111));
|
| + builder.AppendCString("...<omitted>...");
|
| + builder.AppendString(isolate->factory()->NewSubString(
|
| + fun_str, fun_str->length() - 2, fun_str->length()));
|
| +
|
| + return builder.Finish().ToHandleChecked();
|
| + }
|
| + return fun_str;
|
| + } else if (input->IsSymbol()) {
|
| + // -- S y m b o l
|
| + Handle<Symbol> symbol = Handle<Symbol>::cast(input);
|
| +
|
| + IncrementalStringBuilder builder(isolate);
|
| + builder.AppendCString("Symbol(");
|
| + if (symbol->name()->IsString()) {
|
| + builder.AppendString(handle(String::cast(symbol->name()), isolate));
|
| + }
|
| + builder.AppendCharacter(')');
|
| +
|
| + return builder.Finish().ToHandleChecked();
|
| + } else if (input->IsJSReceiver()) {
|
| + // -- J S R e c e i v e r
|
| + Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
|
| + Handle<Object> to_string = JSReceiver::GetDataProperty(
|
| + receiver, isolate->factory()->toString_string());
|
| +
|
| + if (IsErrorObject(isolate, input) ||
|
| + *to_string == *isolate->error_to_string()) {
|
| + // When internally formatting error objects, use a side-effects-free
|
| + // version of Error.prototype.toString independent of the actually
|
| + // installed toString method.
|
| + return NoSideEffectsErrorToString(isolate, input);
|
| + } else if (*to_string == *isolate->object_to_string()) {
|
| + Handle<Object> ctor = JSReceiver::GetDataProperty(
|
| + receiver, isolate->factory()->constructor_string());
|
| + if (ctor->IsFunction()) {
|
| + Handle<String> ctor_name;
|
| + if (ctor->IsJSBoundFunction()) {
|
| + ctor_name = JSBoundFunction::GetName(
|
| + isolate, Handle<JSBoundFunction>::cast(ctor))
|
| + .ToHandleChecked();
|
| + } else if (ctor->IsJSFunction()) {
|
| + Handle<Object> ctor_name_obj =
|
| + JSFunction::GetName(isolate, Handle<JSFunction>::cast(ctor));
|
| + ctor_name = NoSideEffectsToString(isolate, ctor_name_obj);
|
| + }
|
| +
|
| + if (ctor_name->length() != 0) {
|
| + IncrementalStringBuilder builder(isolate);
|
| + builder.AppendCString("#<");
|
| + builder.AppendString(ctor_name);
|
| + builder.AppendCString(">");
|
| +
|
| + return builder.Finish().ToHandleChecked();
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + // At this point, input is either none of the above or a JSReceiver.
|
| +
|
| + Handle<JSReceiver> receiver;
|
| + if (input->IsJSReceiver()) {
|
| + receiver = Handle<JSReceiver>::cast(input);
|
| + } else {
|
| + // This is the only case where Object::ToObject throws.
|
| + DCHECK(!input->IsSmi());
|
| + int constructor_function_index =
|
| + Handle<HeapObject>::cast(input)->map()->GetConstructorFunctionIndex();
|
| + if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
|
| + return isolate->factory()->NewStringFromAsciiChecked("[object Unknown]");
|
| + }
|
| +
|
| + receiver = Object::ToObject(isolate, input, isolate->native_context())
|
| + .ToHandleChecked();
|
| + }
|
| +
|
| + Handle<String> builtin_tag = handle(receiver->class_name(), isolate);
|
| + Handle<Object> tag_obj = JSReceiver::GetDataProperty(
|
| + receiver, isolate->factory()->to_string_tag_symbol());
|
| + Handle<String> tag =
|
| + tag_obj->IsString() ? Handle<String>::cast(tag_obj) : builtin_tag;
|
| +
|
| + IncrementalStringBuilder builder(isolate);
|
| + builder.AppendCString("[object ");
|
| + builder.AppendString(tag);
|
| + builder.AppendCString("]");
|
| +
|
| + return builder.Finish().ToHandleChecked();
|
| +}
|
|
|
| // static
|
| MaybeHandle<Object> Object::ToLength(Isolate* isolate, Handle<Object> input) {
|
|
|