Home | History | Annotate | Download | only in src
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/messages.h"
      6 
      7 #include <memory>
      8 
      9 #include "src/api.h"
     10 #include "src/execution.h"
     11 #include "src/isolate-inl.h"
     12 #include "src/keys.h"
     13 #include "src/string-builder.h"
     14 #include "src/wasm/wasm-module.h"
     15 #include "src/wasm/wasm-objects.h"
     16 
     17 namespace v8 {
     18 namespace internal {
     19 
     20 MessageLocation::MessageLocation(Handle<Script> script, int start_pos,
     21                                  int end_pos)
     22     : script_(script), start_pos_(start_pos), end_pos_(end_pos) {}
     23 MessageLocation::MessageLocation(Handle<Script> script, int start_pos,
     24                                  int end_pos, Handle<SharedFunctionInfo> shared)
     25     : script_(script),
     26       start_pos_(start_pos),
     27       end_pos_(end_pos),
     28       shared_(shared) {}
     29 MessageLocation::MessageLocation() : start_pos_(-1), end_pos_(-1) {}
     30 
     31 // If no message listeners have been registered this one is called
     32 // by default.
     33 void MessageHandler::DefaultMessageReport(Isolate* isolate,
     34                                           const MessageLocation* loc,
     35                                           Handle<Object> message_obj) {
     36   std::unique_ptr<char[]> str = GetLocalizedMessage(isolate, message_obj);
     37   if (loc == NULL) {
     38     PrintF("%s\n", str.get());
     39   } else {
     40     HandleScope scope(isolate);
     41     Handle<Object> data(loc->script()->name(), isolate);
     42     std::unique_ptr<char[]> data_str;
     43     if (data->IsString())
     44       data_str = Handle<String>::cast(data)->ToCString(DISALLOW_NULLS);
     45     PrintF("%s:%i: %s\n", data_str.get() ? data_str.get() : "<unknown>",
     46            loc->start_pos(), str.get());
     47   }
     48 }
     49 
     50 Handle<JSMessageObject> MessageHandler::MakeMessageObject(
     51     Isolate* isolate, MessageTemplate::Template message,
     52     const MessageLocation* location, Handle<Object> argument,
     53     Handle<JSArray> stack_frames) {
     54   Factory* factory = isolate->factory();
     55 
     56   int start = -1;
     57   int end = -1;
     58   Handle<Object> script_handle = factory->undefined_value();
     59   if (location != NULL) {
     60     start = location->start_pos();
     61     end = location->end_pos();
     62     script_handle = Script::GetWrapper(location->script());
     63   } else {
     64     script_handle = Script::GetWrapper(isolate->factory()->empty_script());
     65   }
     66 
     67   Handle<Object> stack_frames_handle = stack_frames.is_null()
     68       ? Handle<Object>::cast(factory->undefined_value())
     69       : Handle<Object>::cast(stack_frames);
     70 
     71   Handle<JSMessageObject> message_obj = factory->NewJSMessageObject(
     72       message, argument, start, end, script_handle, stack_frames_handle);
     73 
     74   return message_obj;
     75 }
     76 
     77 void MessageHandler::ReportMessage(Isolate* isolate, const MessageLocation* loc,
     78                                    Handle<JSMessageObject> message) {
     79   v8::Local<v8::Message> api_message_obj = v8::Utils::MessageToLocal(message);
     80 
     81   if (api_message_obj->ErrorLevel() == v8::Isolate::kMessageError) {
     82     // We are calling into embedder's code which can throw exceptions.
     83     // Thus we need to save current exception state, reset it to the clean one
     84     // and ignore scheduled exceptions callbacks can throw.
     85 
     86     // We pass the exception object into the message handler callback though.
     87     Object* exception_object = isolate->heap()->undefined_value();
     88     if (isolate->has_pending_exception()) {
     89       exception_object = isolate->pending_exception();
     90     }
     91     Handle<Object> exception(exception_object, isolate);
     92 
     93     Isolate::ExceptionScope exception_scope(isolate);
     94     isolate->clear_pending_exception();
     95     isolate->set_external_caught_exception(false);
     96 
     97     // Turn the exception on the message into a string if it is an object.
     98     if (message->argument()->IsJSObject()) {
     99       HandleScope scope(isolate);
    100       Handle<Object> argument(message->argument(), isolate);
    101 
    102       MaybeHandle<Object> maybe_stringified;
    103       Handle<Object> stringified;
    104       // Make sure we don't leak uncaught internally generated Error objects.
    105       if (argument->IsJSError()) {
    106         maybe_stringified = Object::NoSideEffectsToString(isolate, argument);
    107       } else {
    108         v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
    109         catcher.SetVerbose(false);
    110         catcher.SetCaptureMessage(false);
    111 
    112         maybe_stringified = Object::ToString(isolate, argument);
    113       }
    114 
    115       if (!maybe_stringified.ToHandle(&stringified)) {
    116         stringified =
    117             isolate->factory()->NewStringFromAsciiChecked("exception");
    118       }
    119       message->set_argument(*stringified);
    120     }
    121 
    122     v8::Local<v8::Value> api_exception_obj = v8::Utils::ToLocal(exception);
    123     ReportMessageNoExceptions(isolate, loc, message, api_exception_obj);
    124   } else {
    125     ReportMessageNoExceptions(isolate, loc, message, v8::Local<v8::Value>());
    126   }
    127 }
    128 
    129 void MessageHandler::ReportMessageNoExceptions(
    130     Isolate* isolate, const MessageLocation* loc, Handle<Object> message,
    131     v8::Local<v8::Value> api_exception_obj) {
    132   v8::Local<v8::Message> api_message_obj = v8::Utils::MessageToLocal(message);
    133   int error_level = api_message_obj->ErrorLevel();
    134 
    135   Handle<TemplateList> global_listeners =
    136       isolate->factory()->message_listeners();
    137   int global_length = global_listeners->length();
    138   if (global_length == 0) {
    139     DefaultMessageReport(isolate, loc, message);
    140     if (isolate->has_scheduled_exception()) {
    141       isolate->clear_scheduled_exception();
    142     }
    143   } else {
    144     for (int i = 0; i < global_length; i++) {
    145       HandleScope scope(isolate);
    146       if (global_listeners->get(i)->IsUndefined(isolate)) continue;
    147       FixedArray* listener = FixedArray::cast(global_listeners->get(i));
    148       Foreign* callback_obj = Foreign::cast(listener->get(0));
    149       int32_t message_levels =
    150           static_cast<int32_t>(Smi::cast(listener->get(2))->value());
    151       if (!(message_levels & error_level)) {
    152         continue;
    153       }
    154       v8::MessageCallback callback =
    155           FUNCTION_CAST<v8::MessageCallback>(callback_obj->foreign_address());
    156       Handle<Object> callback_data(listener->get(1), isolate);
    157       {
    158         // Do not allow exceptions to propagate.
    159         v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
    160         callback(api_message_obj, callback_data->IsUndefined(isolate)
    161                                       ? api_exception_obj
    162                                       : v8::Utils::ToLocal(callback_data));
    163       }
    164       if (isolate->has_scheduled_exception()) {
    165         isolate->clear_scheduled_exception();
    166       }
    167     }
    168   }
    169 }
    170 
    171 
    172 Handle<String> MessageHandler::GetMessage(Isolate* isolate,
    173                                           Handle<Object> data) {
    174   Handle<JSMessageObject> message = Handle<JSMessageObject>::cast(data);
    175   Handle<Object> arg = Handle<Object>(message->argument(), isolate);
    176   return MessageTemplate::FormatMessage(isolate, message->type(), arg);
    177 }
    178 
    179 std::unique_ptr<char[]> MessageHandler::GetLocalizedMessage(
    180     Isolate* isolate, Handle<Object> data) {
    181   HandleScope scope(isolate);
    182   return GetMessage(isolate, data)->ToCString(DISALLOW_NULLS);
    183 }
    184 
    185 namespace {
    186 
    187 Object* EvalFromFunctionName(Isolate* isolate, Handle<Script> script) {
    188   if (script->eval_from_shared()->IsUndefined(isolate))
    189     return isolate->heap()->undefined_value();
    190 
    191   Handle<SharedFunctionInfo> shared(
    192       SharedFunctionInfo::cast(script->eval_from_shared()));
    193   // Find the name of the function calling eval.
    194   if (shared->name()->BooleanValue()) {
    195     return shared->name();
    196   }
    197 
    198   return shared->inferred_name();
    199 }
    200 
    201 Object* EvalFromScript(Isolate* isolate, Handle<Script> script) {
    202   if (script->eval_from_shared()->IsUndefined(isolate))
    203     return isolate->heap()->undefined_value();
    204 
    205   Handle<SharedFunctionInfo> eval_from_shared(
    206       SharedFunctionInfo::cast(script->eval_from_shared()));
    207   return eval_from_shared->script()->IsScript()
    208              ? eval_from_shared->script()
    209              : isolate->heap()->undefined_value();
    210 }
    211 
    212 MaybeHandle<String> FormatEvalOrigin(Isolate* isolate, Handle<Script> script) {
    213   Handle<Object> sourceURL(script->GetNameOrSourceURL(), isolate);
    214   if (!sourceURL->IsUndefined(isolate)) {
    215     DCHECK(sourceURL->IsString());
    216     return Handle<String>::cast(sourceURL);
    217   }
    218 
    219   IncrementalStringBuilder builder(isolate);
    220   builder.AppendCString("eval at ");
    221 
    222   Handle<Object> eval_from_function_name =
    223       handle(EvalFromFunctionName(isolate, script), isolate);
    224   if (eval_from_function_name->BooleanValue()) {
    225     Handle<String> str;
    226     ASSIGN_RETURN_ON_EXCEPTION(
    227         isolate, str, Object::ToString(isolate, eval_from_function_name),
    228         String);
    229     builder.AppendString(str);
    230   } else {
    231     builder.AppendCString("<anonymous>");
    232   }
    233 
    234   Handle<Object> eval_from_script_obj =
    235       handle(EvalFromScript(isolate, script), isolate);
    236   if (eval_from_script_obj->IsScript()) {
    237     Handle<Script> eval_from_script =
    238         Handle<Script>::cast(eval_from_script_obj);
    239     builder.AppendCString(" (");
    240     if (eval_from_script->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
    241       // Eval script originated from another eval.
    242       Handle<String> str;
    243       ASSIGN_RETURN_ON_EXCEPTION(
    244           isolate, str, FormatEvalOrigin(isolate, eval_from_script), String);
    245       builder.AppendString(str);
    246     } else {
    247       DCHECK(eval_from_script->compilation_type() !=
    248              Script::COMPILATION_TYPE_EVAL);
    249       // eval script originated from "real" source.
    250       Handle<Object> name_obj = handle(eval_from_script->name(), isolate);
    251       if (eval_from_script->name()->IsString()) {
    252         builder.AppendString(Handle<String>::cast(name_obj));
    253 
    254         Script::PositionInfo info;
    255         if (Script::GetPositionInfo(eval_from_script, script->GetEvalPosition(),
    256                                     &info, Script::NO_OFFSET)) {
    257           builder.AppendCString(":");
    258 
    259           Handle<String> str = isolate->factory()->NumberToString(
    260               handle(Smi::FromInt(info.line + 1), isolate));
    261           builder.AppendString(str);
    262 
    263           builder.AppendCString(":");
    264 
    265           str = isolate->factory()->NumberToString(
    266               handle(Smi::FromInt(info.column + 1), isolate));
    267           builder.AppendString(str);
    268         }
    269       } else {
    270         DCHECK(!eval_from_script->name()->IsString());
    271         builder.AppendCString("unknown source");
    272       }
    273     }
    274     builder.AppendCString(")");
    275   }
    276 
    277   Handle<String> result;
    278   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String);
    279   return result;
    280 }
    281 
    282 }  // namespace
    283 
    284 Handle<Object> StackFrameBase::GetEvalOrigin() {
    285   if (!HasScript()) return isolate_->factory()->undefined_value();
    286   return FormatEvalOrigin(isolate_, GetScript()).ToHandleChecked();
    287 }
    288 
    289 bool StackFrameBase::IsEval() {
    290   return HasScript() &&
    291          GetScript()->compilation_type() == Script::COMPILATION_TYPE_EVAL;
    292 }
    293 
    294 void JSStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array,
    295                                   int frame_ix) {
    296   DCHECK(!array->IsWasmFrame(frame_ix));
    297   isolate_ = isolate;
    298   receiver_ = handle(array->Receiver(frame_ix), isolate);
    299   function_ = handle(array->Function(frame_ix), isolate);
    300   code_ = handle(array->Code(frame_ix), isolate);
    301   offset_ = array->Offset(frame_ix)->value();
    302 
    303   const int flags = array->Flags(frame_ix)->value();
    304   force_constructor_ = (flags & FrameArray::kForceConstructor) != 0;
    305   is_strict_ = (flags & FrameArray::kIsStrict) != 0;
    306 }
    307 
    308 JSStackFrame::JSStackFrame() {}
    309 
    310 JSStackFrame::JSStackFrame(Isolate* isolate, Handle<Object> receiver,
    311                            Handle<JSFunction> function,
    312                            Handle<AbstractCode> code, int offset)
    313     : StackFrameBase(isolate),
    314       receiver_(receiver),
    315       function_(function),
    316       code_(code),
    317       offset_(offset),
    318       force_constructor_(false),
    319       is_strict_(false) {}
    320 
    321 Handle<Object> JSStackFrame::GetFunction() const {
    322   return Handle<Object>::cast(function_);
    323 }
    324 
    325 Handle<Object> JSStackFrame::GetFileName() {
    326   if (!HasScript()) return isolate_->factory()->null_value();
    327   return handle(GetScript()->name(), isolate_);
    328 }
    329 
    330 Handle<Object> JSStackFrame::GetFunctionName() {
    331   Handle<String> result = JSFunction::GetName(function_);
    332   if (result->length() != 0) return result;
    333 
    334   if (HasScript() &&
    335       GetScript()->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
    336     return isolate_->factory()->eval_string();
    337   }
    338   return isolate_->factory()->null_value();
    339 }
    340 
    341 namespace {
    342 
    343 bool CheckMethodName(Isolate* isolate, Handle<JSObject> obj, Handle<Name> name,
    344                      Handle<JSFunction> fun,
    345                      LookupIterator::Configuration config) {
    346   LookupIterator iter =
    347       LookupIterator::PropertyOrElement(isolate, obj, name, config);
    348   if (iter.state() == LookupIterator::DATA) {
    349     return iter.GetDataValue().is_identical_to(fun);
    350   } else if (iter.state() == LookupIterator::ACCESSOR) {
    351     Handle<Object> accessors = iter.GetAccessors();
    352     if (accessors->IsAccessorPair()) {
    353       Handle<AccessorPair> pair = Handle<AccessorPair>::cast(accessors);
    354       return pair->getter() == *fun || pair->setter() == *fun;
    355     }
    356   }
    357   return false;
    358 }
    359 
    360 Handle<Object> ScriptNameOrSourceUrl(Handle<Script> script, Isolate* isolate) {
    361   Object* name_or_url = script->source_url();
    362   if (!name_or_url->IsString()) name_or_url = script->name();
    363   return handle(name_or_url, isolate);
    364 }
    365 
    366 }  // namespace
    367 
    368 Handle<Object> JSStackFrame::GetScriptNameOrSourceUrl() {
    369   if (!HasScript()) return isolate_->factory()->null_value();
    370   return ScriptNameOrSourceUrl(GetScript(), isolate_);
    371 }
    372 
    373 Handle<Object> JSStackFrame::GetMethodName() {
    374   if (receiver_->IsNullOrUndefined(isolate_)) {
    375     return isolate_->factory()->null_value();
    376   }
    377 
    378   Handle<JSReceiver> receiver =
    379       Object::ToObject(isolate_, receiver_).ToHandleChecked();
    380   if (!receiver->IsJSObject()) {
    381     return isolate_->factory()->null_value();
    382   }
    383 
    384   Handle<JSObject> obj = Handle<JSObject>::cast(receiver);
    385   Handle<Object> function_name(function_->shared()->name(), isolate_);
    386   if (function_name->IsString()) {
    387     Handle<String> name = Handle<String>::cast(function_name);
    388     // ES2015 gives getters and setters name prefixes which must
    389     // be stripped to find the property name.
    390     if (name->IsUtf8EqualTo(CStrVector("get "), true) ||
    391         name->IsUtf8EqualTo(CStrVector("set "), true)) {
    392       name = isolate_->factory()->NewProperSubString(name, 4, name->length());
    393     }
    394     if (CheckMethodName(isolate_, obj, name, function_,
    395                         LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR)) {
    396       return name;
    397     }
    398   }
    399 
    400   HandleScope outer_scope(isolate_);
    401   Handle<Object> result;
    402   for (PrototypeIterator iter(isolate_, obj, kStartAtReceiver); !iter.IsAtEnd();
    403        iter.Advance()) {
    404     Handle<Object> current = PrototypeIterator::GetCurrent(iter);
    405     if (!current->IsJSObject()) break;
    406     Handle<JSObject> current_obj = Handle<JSObject>::cast(current);
    407     if (current_obj->IsAccessCheckNeeded()) break;
    408     Handle<FixedArray> keys =
    409         KeyAccumulator::GetOwnEnumPropertyKeys(isolate_, current_obj);
    410     for (int i = 0; i < keys->length(); i++) {
    411       HandleScope inner_scope(isolate_);
    412       if (!keys->get(i)->IsName()) continue;
    413       Handle<Name> name_key(Name::cast(keys->get(i)), isolate_);
    414       if (!CheckMethodName(isolate_, current_obj, name_key, function_,
    415                            LookupIterator::OWN_SKIP_INTERCEPTOR))
    416         continue;
    417       // Return null in case of duplicates to avoid confusion.
    418       if (!result.is_null()) return isolate_->factory()->null_value();
    419       result = inner_scope.CloseAndEscape(name_key);
    420     }
    421   }
    422 
    423   if (!result.is_null()) return outer_scope.CloseAndEscape(result);
    424   return isolate_->factory()->null_value();
    425 }
    426 
    427 Handle<Object> JSStackFrame::GetTypeName() {
    428   // TODO(jgruber): Check for strict/constructor here as in
    429   // CallSitePrototypeGetThis.
    430 
    431   if (receiver_->IsNullOrUndefined(isolate_))
    432     return isolate_->factory()->null_value();
    433 
    434   if (receiver_->IsJSProxy()) return isolate_->factory()->Proxy_string();
    435 
    436   Handle<JSReceiver> receiver_object =
    437       Object::ToObject(isolate_, receiver_).ToHandleChecked();
    438   return JSReceiver::GetConstructorName(receiver_object);
    439 }
    440 
    441 int JSStackFrame::GetLineNumber() {
    442   DCHECK_LE(0, GetPosition());
    443   if (HasScript()) return Script::GetLineNumber(GetScript(), GetPosition()) + 1;
    444   return -1;
    445 }
    446 
    447 int JSStackFrame::GetColumnNumber() {
    448   DCHECK_LE(0, GetPosition());
    449   if (HasScript()) {
    450     return Script::GetColumnNumber(GetScript(), GetPosition()) + 1;
    451   }
    452   return -1;
    453 }
    454 
    455 bool JSStackFrame::IsNative() {
    456   return HasScript() && GetScript()->type() == Script::TYPE_NATIVE;
    457 }
    458 
    459 bool JSStackFrame::IsToplevel() {
    460   return receiver_->IsJSGlobalProxy() || receiver_->IsNullOrUndefined(isolate_);
    461 }
    462 
    463 bool JSStackFrame::IsConstructor() {
    464   if (force_constructor_) return true;
    465   if (!receiver_->IsJSObject()) return false;
    466   Handle<Object> constructor =
    467       JSReceiver::GetDataProperty(Handle<JSObject>::cast(receiver_),
    468                                   isolate_->factory()->constructor_string());
    469   return constructor.is_identical_to(function_);
    470 }
    471 
    472 namespace {
    473 
    474 bool IsNonEmptyString(Handle<Object> object) {
    475   return (object->IsString() && String::cast(*object)->length() > 0);
    476 }
    477 
    478 void AppendFileLocation(Isolate* isolate, StackFrameBase* call_site,
    479                         IncrementalStringBuilder* builder) {
    480   if (call_site->IsNative()) {
    481     builder->AppendCString("native");
    482     return;
    483   }
    484 
    485   Handle<Object> file_name = call_site->GetScriptNameOrSourceUrl();
    486   if (!file_name->IsString() && call_site->IsEval()) {
    487     Handle<Object> eval_origin = call_site->GetEvalOrigin();
    488     DCHECK(eval_origin->IsString());
    489     builder->AppendString(Handle<String>::cast(eval_origin));
    490     builder->AppendCString(", ");  // Expecting source position to follow.
    491   }
    492 
    493   if (IsNonEmptyString(file_name)) {
    494     builder->AppendString(Handle<String>::cast(file_name));
    495   } else {
    496     // Source code does not originate from a file and is not native, but we
    497     // can still get the source position inside the source string, e.g. in
    498     // an eval string.
    499     builder->AppendCString("<anonymous>");
    500   }
    501 
    502   int line_number = call_site->GetLineNumber();
    503   if (line_number != -1) {
    504     builder->AppendCharacter(':');
    505     Handle<String> line_string = isolate->factory()->NumberToString(
    506         handle(Smi::FromInt(line_number), isolate), isolate);
    507     builder->AppendString(line_string);
    508 
    509     int column_number = call_site->GetColumnNumber();
    510     if (column_number != -1) {
    511       builder->AppendCharacter(':');
    512       Handle<String> column_string = isolate->factory()->NumberToString(
    513           handle(Smi::FromInt(column_number), isolate), isolate);
    514       builder->AppendString(column_string);
    515     }
    516   }
    517 }
    518 
    519 int StringIndexOf(Isolate* isolate, Handle<String> subject,
    520                   Handle<String> pattern) {
    521   if (pattern->length() > subject->length()) return -1;
    522   return String::IndexOf(isolate, subject, pattern, 0);
    523 }
    524 
    525 // Returns true iff
    526 // 1. the subject ends with '.' + pattern, or
    527 // 2. subject == pattern.
    528 bool StringEndsWithMethodName(Isolate* isolate, Handle<String> subject,
    529                               Handle<String> pattern) {
    530   if (String::Equals(subject, pattern)) return true;
    531 
    532   FlatStringReader subject_reader(isolate, String::Flatten(subject));
    533   FlatStringReader pattern_reader(isolate, String::Flatten(pattern));
    534 
    535   int pattern_index = pattern_reader.length() - 1;
    536   int subject_index = subject_reader.length() - 1;
    537   for (int i = 0; i <= pattern_reader.length(); i++) {  // Iterate over len + 1.
    538     if (subject_index < 0) {
    539       return false;
    540     }
    541 
    542     const uc32 subject_char = subject_reader.Get(subject_index);
    543     if (i == pattern_reader.length()) {
    544       if (subject_char != '.') return false;
    545     } else if (subject_char != pattern_reader.Get(pattern_index)) {
    546       return false;
    547     }
    548 
    549     pattern_index--;
    550     subject_index--;
    551   }
    552 
    553   return true;
    554 }
    555 
    556 void AppendMethodCall(Isolate* isolate, JSStackFrame* call_site,
    557                       IncrementalStringBuilder* builder) {
    558   Handle<Object> type_name = call_site->GetTypeName();
    559   Handle<Object> method_name = call_site->GetMethodName();
    560   Handle<Object> function_name = call_site->GetFunctionName();
    561 
    562   if (IsNonEmptyString(function_name)) {
    563     Handle<String> function_string = Handle<String>::cast(function_name);
    564     if (IsNonEmptyString(type_name)) {
    565       Handle<String> type_string = Handle<String>::cast(type_name);
    566       bool starts_with_type_name =
    567           (StringIndexOf(isolate, function_string, type_string) == 0);
    568       if (!starts_with_type_name) {
    569         builder->AppendString(type_string);
    570         builder->AppendCharacter('.');
    571       }
    572     }
    573     builder->AppendString(function_string);
    574 
    575     if (IsNonEmptyString(method_name)) {
    576       Handle<String> method_string = Handle<String>::cast(method_name);
    577       if (!StringEndsWithMethodName(isolate, function_string, method_string)) {
    578         builder->AppendCString(" [as ");
    579         builder->AppendString(method_string);
    580         builder->AppendCharacter(']');
    581       }
    582     }
    583   } else {
    584     builder->AppendString(Handle<String>::cast(type_name));
    585     builder->AppendCharacter('.');
    586     if (IsNonEmptyString(method_name)) {
    587       builder->AppendString(Handle<String>::cast(method_name));
    588     } else {
    589       builder->AppendCString("<anonymous>");
    590     }
    591   }
    592 }
    593 
    594 }  // namespace
    595 
    596 MaybeHandle<String> JSStackFrame::ToString() {
    597   IncrementalStringBuilder builder(isolate_);
    598 
    599   Handle<Object> function_name = GetFunctionName();
    600 
    601   const bool is_toplevel = IsToplevel();
    602   const bool is_constructor = IsConstructor();
    603   const bool is_method_call = !(is_toplevel || is_constructor);
    604 
    605   if (is_method_call) {
    606     AppendMethodCall(isolate_, this, &builder);
    607   } else if (is_constructor) {
    608     builder.AppendCString("new ");
    609     if (IsNonEmptyString(function_name)) {
    610       builder.AppendString(Handle<String>::cast(function_name));
    611     } else {
    612       builder.AppendCString("<anonymous>");
    613     }
    614   } else if (IsNonEmptyString(function_name)) {
    615     builder.AppendString(Handle<String>::cast(function_name));
    616   } else {
    617     AppendFileLocation(isolate_, this, &builder);
    618     return builder.Finish();
    619   }
    620 
    621   builder.AppendCString(" (");
    622   AppendFileLocation(isolate_, this, &builder);
    623   builder.AppendCString(")");
    624 
    625   return builder.Finish();
    626 }
    627 
    628 int JSStackFrame::GetPosition() const { return code_->SourcePosition(offset_); }
    629 
    630 bool JSStackFrame::HasScript() const {
    631   return function_->shared()->script()->IsScript();
    632 }
    633 
    634 Handle<Script> JSStackFrame::GetScript() const {
    635   return handle(Script::cast(function_->shared()->script()), isolate_);
    636 }
    637 
    638 WasmStackFrame::WasmStackFrame() {}
    639 
    640 void WasmStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array,
    641                                     int frame_ix) {
    642   // This function is called for both wasm and asm.js->wasm frames.
    643   DCHECK(array->IsWasmFrame(frame_ix) || array->IsAsmJsWasmFrame(frame_ix));
    644   isolate_ = isolate;
    645   wasm_instance_ = handle(array->WasmInstance(frame_ix), isolate);
    646   wasm_func_index_ = array->WasmFunctionIndex(frame_ix)->value();
    647   code_ = handle(array->Code(frame_ix), isolate);
    648   offset_ = array->Offset(frame_ix)->value();
    649 }
    650 
    651 Handle<Object> WasmStackFrame::GetFunction() const {
    652   Handle<Object> obj(Smi::FromInt(wasm_func_index_), isolate_);
    653   return obj;
    654 }
    655 
    656 Handle<Object> WasmStackFrame::GetFunctionName() {
    657   Handle<Object> name;
    658   Handle<WasmCompiledModule> compiled_module(
    659       Handle<WasmInstanceObject>::cast(wasm_instance_)->compiled_module(),
    660       isolate_);
    661   if (!WasmCompiledModule::GetFunctionNameOrNull(isolate_, compiled_module,
    662                                                  wasm_func_index_)
    663            .ToHandle(&name)) {
    664     name = isolate_->factory()->null_value();
    665   }
    666   return name;
    667 }
    668 
    669 MaybeHandle<String> WasmStackFrame::ToString() {
    670   IncrementalStringBuilder builder(isolate_);
    671 
    672   Handle<Object> name = GetFunctionName();
    673   if (name->IsNull(isolate_)) {
    674     builder.AppendCString("<WASM UNNAMED>");
    675   } else {
    676     DCHECK(name->IsString());
    677     builder.AppendString(Handle<String>::cast(name));
    678   }
    679 
    680   builder.AppendCString(" (<WASM>[");
    681 
    682   Handle<Smi> ix(Smi::FromInt(wasm_func_index_), isolate_);
    683   builder.AppendString(isolate_->factory()->NumberToString(ix));
    684 
    685   builder.AppendCString("]+");
    686 
    687   Handle<Object> pos(Smi::FromInt(GetPosition()), isolate_);
    688   builder.AppendString(isolate_->factory()->NumberToString(pos));
    689   builder.AppendCString(")");
    690 
    691   return builder.Finish();
    692 }
    693 
    694 int WasmStackFrame::GetPosition() const {
    695   // TODO(wasm): Clean this up (bug 5007).
    696   return (offset_ < 0) ? (-1 - offset_) : code_->SourcePosition(offset_);
    697 }
    698 
    699 Handle<Object> WasmStackFrame::Null() const {
    700   return isolate_->factory()->null_value();
    701 }
    702 
    703 bool WasmStackFrame::HasScript() const { return true; }
    704 
    705 Handle<Script> WasmStackFrame::GetScript() const {
    706   return handle(
    707       WasmInstanceObject::cast(*wasm_instance_)->compiled_module()->script(),
    708       isolate_);
    709 }
    710 
    711 AsmJsWasmStackFrame::AsmJsWasmStackFrame() {}
    712 
    713 void AsmJsWasmStackFrame::FromFrameArray(Isolate* isolate,
    714                                          Handle<FrameArray> array,
    715                                          int frame_ix) {
    716   DCHECK(array->IsAsmJsWasmFrame(frame_ix));
    717   WasmStackFrame::FromFrameArray(isolate, array, frame_ix);
    718   is_at_number_conversion_ =
    719       array->Flags(frame_ix)->value() & FrameArray::kAsmJsAtNumberConversion;
    720 }
    721 
    722 Handle<Object> AsmJsWasmStackFrame::GetReceiver() const {
    723   return isolate_->global_proxy();
    724 }
    725 
    726 Handle<Object> AsmJsWasmStackFrame::GetFunction() const {
    727   // TODO(clemensh): Return lazily created JSFunction.
    728   return Null();
    729 }
    730 
    731 Handle<Object> AsmJsWasmStackFrame::GetFileName() {
    732   Handle<Script> script =
    733       wasm::GetScript(Handle<JSObject>::cast(wasm_instance_));
    734   DCHECK_EQ(Script::TYPE_NORMAL, script->type());
    735   return handle(script->name(), isolate_);
    736 }
    737 
    738 Handle<Object> AsmJsWasmStackFrame::GetScriptNameOrSourceUrl() {
    739   Handle<Script> script =
    740       wasm::GetScript(Handle<JSObject>::cast(wasm_instance_));
    741   DCHECK_EQ(Script::TYPE_NORMAL, script->type());
    742   return ScriptNameOrSourceUrl(script, isolate_);
    743 }
    744 
    745 int AsmJsWasmStackFrame::GetPosition() const {
    746   DCHECK_LE(0, offset_);
    747   int byte_offset = code_->SourcePosition(offset_);
    748   Handle<WasmCompiledModule> compiled_module(
    749       WasmInstanceObject::cast(*wasm_instance_)->compiled_module(), isolate_);
    750   DCHECK_LE(0, byte_offset);
    751   return WasmCompiledModule::GetAsmJsSourcePosition(
    752       compiled_module, wasm_func_index_, static_cast<uint32_t>(byte_offset),
    753       is_at_number_conversion_);
    754 }
    755 
    756 int AsmJsWasmStackFrame::GetLineNumber() {
    757   DCHECK_LE(0, GetPosition());
    758   Handle<Script> script =
    759       wasm::GetScript(Handle<JSObject>::cast(wasm_instance_));
    760   DCHECK_EQ(Script::TYPE_NORMAL, script->type());
    761   return Script::GetLineNumber(script, GetPosition()) + 1;
    762 }
    763 
    764 int AsmJsWasmStackFrame::GetColumnNumber() {
    765   DCHECK_LE(0, GetPosition());
    766   Handle<Script> script =
    767       wasm::GetScript(Handle<JSObject>::cast(wasm_instance_));
    768   DCHECK_EQ(Script::TYPE_NORMAL, script->type());
    769   return Script::GetColumnNumber(script, GetPosition()) + 1;
    770 }
    771 
    772 MaybeHandle<String> AsmJsWasmStackFrame::ToString() {
    773   // The string should look exactly as the respective javascript frame string.
    774   // Keep this method in line to JSStackFrame::ToString().
    775 
    776   IncrementalStringBuilder builder(isolate_);
    777 
    778   Handle<Object> function_name = GetFunctionName();
    779 
    780   if (IsNonEmptyString(function_name)) {
    781     builder.AppendString(Handle<String>::cast(function_name));
    782     builder.AppendCString(" (");
    783   }
    784 
    785   AppendFileLocation(isolate_, this, &builder);
    786 
    787   if (IsNonEmptyString(function_name)) builder.AppendCString(")");
    788 
    789   return builder.Finish();
    790 }
    791 
    792 FrameArrayIterator::FrameArrayIterator(Isolate* isolate,
    793                                        Handle<FrameArray> array, int frame_ix)
    794     : isolate_(isolate), array_(array), next_frame_ix_(frame_ix) {}
    795 
    796 bool FrameArrayIterator::HasNext() const {
    797   return (next_frame_ix_ < array_->FrameCount());
    798 }
    799 
    800 void FrameArrayIterator::Next() { next_frame_ix_++; }
    801 
    802 StackFrameBase* FrameArrayIterator::Frame() {
    803   DCHECK(HasNext());
    804   const int flags = array_->Flags(next_frame_ix_)->value();
    805   switch (flags & (FrameArray::kIsWasmFrame | FrameArray::kIsAsmJsWasmFrame)) {
    806     case 0:
    807       // JavaScript Frame.
    808       js_frame_.FromFrameArray(isolate_, array_, next_frame_ix_);
    809       return &js_frame_;
    810     case FrameArray::kIsWasmFrame:
    811       // Wasm Frame;
    812       wasm_frame_.FromFrameArray(isolate_, array_, next_frame_ix_);
    813       return &wasm_frame_;
    814     case FrameArray::kIsAsmJsWasmFrame:
    815       // Asm.js Wasm Frame:
    816       asm_wasm_frame_.FromFrameArray(isolate_, array_, next_frame_ix_);
    817       return &asm_wasm_frame_;
    818     default:
    819       UNREACHABLE();
    820       return nullptr;
    821   }
    822 }
    823 
    824 namespace {
    825 
    826 MaybeHandle<Object> ConstructCallSite(Isolate* isolate,
    827                                       Handle<FrameArray> frame_array,
    828                                       int frame_index) {
    829   Handle<JSFunction> target =
    830       handle(isolate->native_context()->callsite_function(), isolate);
    831 
    832   Handle<JSObject> obj;
    833   ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, JSObject::New(target, target),
    834                              Object);
    835 
    836   Handle<Symbol> key = isolate->factory()->call_site_frame_array_symbol();
    837   RETURN_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
    838                                    obj, key, frame_array, DONT_ENUM),
    839                       Object);
    840 
    841   key = isolate->factory()->call_site_frame_index_symbol();
    842   Handle<Object> value(Smi::FromInt(frame_index), isolate);
    843   RETURN_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
    844                                    obj, key, value, DONT_ENUM),
    845                       Object);
    846 
    847   return obj;
    848 }
    849 
    850 // Convert the raw frames as written by Isolate::CaptureSimpleStackTrace into
    851 // a JSArray of JSCallSite objects.
    852 MaybeHandle<JSArray> GetStackFrames(Isolate* isolate,
    853                                     Handle<FrameArray> elems) {
    854   const int frame_count = elems->FrameCount();
    855 
    856   Handle<FixedArray> frames = isolate->factory()->NewFixedArray(frame_count);
    857   for (int i = 0; i < frame_count; i++) {
    858     Handle<Object> site;
    859     ASSIGN_RETURN_ON_EXCEPTION(isolate, site,
    860                                ConstructCallSite(isolate, elems, i), JSArray);
    861     frames->set(i, *site);
    862   }
    863 
    864   return isolate->factory()->NewJSArrayWithElements(frames);
    865 }
    866 
    867 MaybeHandle<Object> AppendErrorString(Isolate* isolate, Handle<Object> error,
    868                                       IncrementalStringBuilder* builder) {
    869   MaybeHandle<String> err_str =
    870       ErrorUtils::ToString(isolate, Handle<Object>::cast(error));
    871   if (err_str.is_null()) {
    872     // Error.toString threw. Try to return a string representation of the thrown
    873     // exception instead.
    874 
    875     DCHECK(isolate->has_pending_exception());
    876     Handle<Object> pending_exception =
    877         handle(isolate->pending_exception(), isolate);
    878     isolate->clear_pending_exception();
    879 
    880     err_str = ErrorUtils::ToString(isolate, pending_exception);
    881     if (err_str.is_null()) {
    882       // Formatting the thrown exception threw again, give up.
    883       DCHECK(isolate->has_pending_exception());
    884       isolate->clear_pending_exception();
    885 
    886       builder->AppendCString("<error>");
    887     } else {
    888       // Formatted thrown exception successfully, append it.
    889       builder->AppendCString("<error: ");
    890       builder->AppendString(err_str.ToHandleChecked());
    891       builder->AppendCharacter('>');
    892     }
    893   } else {
    894     builder->AppendString(err_str.ToHandleChecked());
    895   }
    896 
    897   return error;
    898 }
    899 
    900 class PrepareStackTraceScope {
    901  public:
    902   explicit PrepareStackTraceScope(Isolate* isolate) : isolate_(isolate) {
    903     DCHECK(!isolate_->formatting_stack_trace());
    904     isolate_->set_formatting_stack_trace(true);
    905   }
    906 
    907   ~PrepareStackTraceScope() { isolate_->set_formatting_stack_trace(false); }
    908 
    909  private:
    910   Isolate* isolate_;
    911 
    912   DISALLOW_COPY_AND_ASSIGN(PrepareStackTraceScope);
    913 };
    914 
    915 }  // namespace
    916 
    917 // static
    918 MaybeHandle<Object> ErrorUtils::FormatStackTrace(Isolate* isolate,
    919                                                  Handle<JSObject> error,
    920                                                  Handle<Object> raw_stack) {
    921   DCHECK(raw_stack->IsJSArray());
    922   Handle<JSArray> raw_stack_array = Handle<JSArray>::cast(raw_stack);
    923 
    924   DCHECK(raw_stack_array->elements()->IsFixedArray());
    925   Handle<FrameArray> elems(FrameArray::cast(raw_stack_array->elements()));
    926 
    927   // If there's a user-specified "prepareStackFrames" function, call it on the
    928   // frames and use its result.
    929 
    930   Handle<JSFunction> global_error = isolate->error_function();
    931   Handle<Object> prepare_stack_trace;
    932   ASSIGN_RETURN_ON_EXCEPTION(
    933       isolate, prepare_stack_trace,
    934       JSFunction::GetProperty(isolate, global_error, "prepareStackTrace"),
    935       Object);
    936 
    937   const bool in_recursion = isolate->formatting_stack_trace();
    938   if (prepare_stack_trace->IsJSFunction() && !in_recursion) {
    939     PrepareStackTraceScope scope(isolate);
    940 
    941     Handle<JSArray> sites;
    942     ASSIGN_RETURN_ON_EXCEPTION(isolate, sites, GetStackFrames(isolate, elems),
    943                                Object);
    944 
    945     const int argc = 2;
    946     ScopedVector<Handle<Object>> argv(argc);
    947 
    948     argv[0] = error;
    949     argv[1] = sites;
    950 
    951     Handle<Object> result;
    952     ASSIGN_RETURN_ON_EXCEPTION(
    953         isolate, result, Execution::Call(isolate, prepare_stack_trace,
    954                                          global_error, argc, argv.start()),
    955         Object);
    956 
    957     return result;
    958   }
    959 
    960   // Otherwise, run our internal formatting logic.
    961 
    962   IncrementalStringBuilder builder(isolate);
    963 
    964   RETURN_ON_EXCEPTION(isolate, AppendErrorString(isolate, error, &builder),
    965                       Object);
    966 
    967   for (FrameArrayIterator it(isolate, elems); it.HasNext(); it.Next()) {
    968     builder.AppendCString("\n    at ");
    969 
    970     StackFrameBase* frame = it.Frame();
    971     MaybeHandle<String> maybe_frame_string = frame->ToString();
    972     if (maybe_frame_string.is_null()) {
    973       // CallSite.toString threw. Try to return a string representation of the
    974       // thrown exception instead.
    975 
    976       DCHECK(isolate->has_pending_exception());
    977       Handle<Object> pending_exception =
    978           handle(isolate->pending_exception(), isolate);
    979       isolate->clear_pending_exception();
    980 
    981       maybe_frame_string = ErrorUtils::ToString(isolate, pending_exception);
    982       if (maybe_frame_string.is_null()) {
    983         // Formatting the thrown exception threw again, give up.
    984 
    985         builder.AppendCString("<error>");
    986       } else {
    987         // Formatted thrown exception successfully, append it.
    988         builder.AppendCString("<error: ");
    989         builder.AppendString(maybe_frame_string.ToHandleChecked());
    990         builder.AppendCString("<error>");
    991       }
    992     } else {
    993       // CallSite.toString completed without throwing.
    994       builder.AppendString(maybe_frame_string.ToHandleChecked());
    995     }
    996   }
    997 
    998   return builder.Finish();
    999 }
   1000 
   1001 Handle<String> MessageTemplate::FormatMessage(Isolate* isolate,
   1002                                               int template_index,
   1003                                               Handle<Object> arg) {
   1004   Factory* factory = isolate->factory();
   1005   Handle<String> result_string = Object::NoSideEffectsToString(isolate, arg);
   1006   MaybeHandle<String> maybe_result_string = MessageTemplate::FormatMessage(
   1007       template_index, result_string, factory->empty_string(),
   1008       factory->empty_string());
   1009   if (!maybe_result_string.ToHandle(&result_string)) {
   1010     return factory->InternalizeOneByteString(STATIC_CHAR_VECTOR("<error>"));
   1011   }
   1012   // A string that has been obtained from JS code in this way is
   1013   // likely to be a complicated ConsString of some sort.  We flatten it
   1014   // here to improve the efficiency of converting it to a C string and
   1015   // other operations that are likely to take place (see GetLocalizedMessage
   1016   // for example).
   1017   return String::Flatten(result_string);
   1018 }
   1019 
   1020 
   1021 const char* MessageTemplate::TemplateString(int template_index) {
   1022   switch (template_index) {
   1023 #define CASE(NAME, STRING) \
   1024   case k##NAME:            \
   1025     return STRING;
   1026     MESSAGE_TEMPLATES(CASE)
   1027 #undef CASE
   1028     case kLastMessage:
   1029     default:
   1030       return NULL;
   1031   }
   1032 }
   1033 
   1034 
   1035 MaybeHandle<String> MessageTemplate::FormatMessage(int template_index,
   1036                                                    Handle<String> arg0,
   1037                                                    Handle<String> arg1,
   1038                                                    Handle<String> arg2) {
   1039   Isolate* isolate = arg0->GetIsolate();
   1040   const char* template_string = TemplateString(template_index);
   1041   if (template_string == NULL) {
   1042     isolate->ThrowIllegalOperation();
   1043     return MaybeHandle<String>();
   1044   }
   1045 
   1046   IncrementalStringBuilder builder(isolate);
   1047 
   1048   unsigned int i = 0;
   1049   Handle<String> args[] = {arg0, arg1, arg2};
   1050   for (const char* c = template_string; *c != '\0'; c++) {
   1051     if (*c == '%') {
   1052       // %% results in verbatim %.
   1053       if (*(c + 1) == '%') {
   1054         c++;
   1055         builder.AppendCharacter('%');
   1056       } else {
   1057         DCHECK(i < arraysize(args));
   1058         Handle<String> arg = args[i++];
   1059         builder.AppendString(arg);
   1060       }
   1061     } else {
   1062       builder.AppendCharacter(*c);
   1063     }
   1064   }
   1065 
   1066   return builder.Finish();
   1067 }
   1068 
   1069 MaybeHandle<Object> ErrorUtils::Construct(
   1070     Isolate* isolate, Handle<JSFunction> target, Handle<Object> new_target,
   1071     Handle<Object> message, FrameSkipMode mode, Handle<Object> caller,
   1072     bool suppress_detailed_trace) {
   1073   // 1. If NewTarget is undefined, let newTarget be the active function object,
   1074   // else let newTarget be NewTarget.
   1075 
   1076   Handle<JSReceiver> new_target_recv =
   1077       new_target->IsJSReceiver() ? Handle<JSReceiver>::cast(new_target)
   1078                                  : Handle<JSReceiver>::cast(target);
   1079 
   1080   // 2. Let O be ? OrdinaryCreateFromConstructor(newTarget, "%ErrorPrototype%",
   1081   //     [[ErrorData]] ).
   1082   Handle<JSObject> err;
   1083   ASSIGN_RETURN_ON_EXCEPTION(isolate, err,
   1084                              JSObject::New(target, new_target_recv), Object);
   1085 
   1086   // 3. If message is not undefined, then
   1087   //  a. Let msg be ? ToString(message).
   1088   //  b. Let msgDesc be the PropertyDescriptor{[[Value]]: msg, [[Writable]]:
   1089   //     true, [[Enumerable]]: false, [[Configurable]]: true}.
   1090   //  c. Perform ! DefinePropertyOrThrow(O, "message", msgDesc).
   1091   // 4. Return O.
   1092 
   1093   if (!message->IsUndefined(isolate)) {
   1094     Handle<String> msg_string;
   1095     ASSIGN_RETURN_ON_EXCEPTION(isolate, msg_string,
   1096                                Object::ToString(isolate, message), Object);
   1097     RETURN_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
   1098                                      err, isolate->factory()->message_string(),
   1099                                      msg_string, DONT_ENUM),
   1100                         Object);
   1101   }
   1102 
   1103   // Optionally capture a more detailed stack trace for the message.
   1104   if (!suppress_detailed_trace) {
   1105     RETURN_ON_EXCEPTION(isolate, isolate->CaptureAndSetDetailedStackTrace(err),
   1106                         Object);
   1107   }
   1108 
   1109   // Capture a simple stack trace for the stack property.
   1110   RETURN_ON_EXCEPTION(isolate,
   1111                       isolate->CaptureAndSetSimpleStackTrace(err, mode, caller),
   1112                       Object);
   1113 
   1114   return err;
   1115 }
   1116 
   1117 namespace {
   1118 
   1119 MaybeHandle<String> GetStringPropertyOrDefault(Isolate* isolate,
   1120                                                Handle<JSReceiver> recv,
   1121                                                Handle<String> key,
   1122                                                Handle<String> default_str) {
   1123   Handle<Object> obj;
   1124   ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, JSObject::GetProperty(recv, key),
   1125                              String);
   1126 
   1127   Handle<String> str;
   1128   if (obj->IsUndefined(isolate)) {
   1129     str = default_str;
   1130   } else {
   1131     ASSIGN_RETURN_ON_EXCEPTION(isolate, str, Object::ToString(isolate, obj),
   1132                                String);
   1133   }
   1134 
   1135   return str;
   1136 }
   1137 
   1138 }  // namespace
   1139 
   1140 // ES6 section 19.5.3.4 Error.prototype.toString ( )
   1141 MaybeHandle<String> ErrorUtils::ToString(Isolate* isolate,
   1142                                          Handle<Object> receiver) {
   1143   // 1. Let O be the this value.
   1144   // 2. If Type(O) is not Object, throw a TypeError exception.
   1145   if (!receiver->IsJSReceiver()) {
   1146     return isolate->Throw<String>(isolate->factory()->NewTypeError(
   1147         MessageTemplate::kIncompatibleMethodReceiver,
   1148         isolate->factory()->NewStringFromAsciiChecked(
   1149             "Error.prototype.toString"),
   1150         receiver));
   1151   }
   1152   Handle<JSReceiver> recv = Handle<JSReceiver>::cast(receiver);
   1153 
   1154   // 3. Let name be ? Get(O, "name").
   1155   // 4. If name is undefined, let name be "Error"; otherwise let name be
   1156   // ? ToString(name).
   1157   Handle<String> name_key = isolate->factory()->name_string();
   1158   Handle<String> name_default = isolate->factory()->Error_string();
   1159   Handle<String> name;
   1160   ASSIGN_RETURN_ON_EXCEPTION(
   1161       isolate, name,
   1162       GetStringPropertyOrDefault(isolate, recv, name_key, name_default),
   1163       String);
   1164 
   1165   // 5. Let msg be ? Get(O, "message").
   1166   // 6. If msg is undefined, let msg be the empty String; otherwise let msg be
   1167   // ? ToString(msg).
   1168   Handle<String> msg_key = isolate->factory()->message_string();
   1169   Handle<String> msg_default = isolate->factory()->empty_string();
   1170   Handle<String> msg;
   1171   ASSIGN_RETURN_ON_EXCEPTION(
   1172       isolate, msg,
   1173       GetStringPropertyOrDefault(isolate, recv, msg_key, msg_default), String);
   1174 
   1175   // 7. If name is the empty String, return msg.
   1176   // 8. If msg is the empty String, return name.
   1177   if (name->length() == 0) return msg;
   1178   if (msg->length() == 0) return name;
   1179 
   1180   // 9. Return the result of concatenating name, the code unit 0x003A (COLON),
   1181   // the code unit 0x0020 (SPACE), and msg.
   1182   IncrementalStringBuilder builder(isolate);
   1183   builder.AppendString(name);
   1184   builder.AppendCString(": ");
   1185   builder.AppendString(msg);
   1186 
   1187   Handle<String> result;
   1188   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String);
   1189   return result;
   1190 }
   1191 
   1192 namespace {
   1193 
   1194 Handle<String> FormatMessage(Isolate* isolate, int template_index,
   1195                              Handle<Object> arg0, Handle<Object> arg1,
   1196                              Handle<Object> arg2) {
   1197   Handle<String> arg0_str = Object::NoSideEffectsToString(isolate, arg0);
   1198   Handle<String> arg1_str = Object::NoSideEffectsToString(isolate, arg1);
   1199   Handle<String> arg2_str = Object::NoSideEffectsToString(isolate, arg2);
   1200 
   1201   isolate->native_context()->IncrementErrorsThrown();
   1202 
   1203   Handle<String> msg;
   1204   if (!MessageTemplate::FormatMessage(template_index, arg0_str, arg1_str,
   1205                                       arg2_str)
   1206            .ToHandle(&msg)) {
   1207     DCHECK(isolate->has_pending_exception());
   1208     isolate->clear_pending_exception();
   1209     return isolate->factory()->NewStringFromAsciiChecked("<error>");
   1210   }
   1211 
   1212   return msg;
   1213 }
   1214 
   1215 }  // namespace
   1216 
   1217 // static
   1218 MaybeHandle<Object> ErrorUtils::MakeGenericError(
   1219     Isolate* isolate, Handle<JSFunction> constructor, int template_index,
   1220     Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg2,
   1221     FrameSkipMode mode) {
   1222   if (FLAG_clear_exceptions_on_js_entry) {
   1223     // This function used to be implemented in JavaScript, and JSEntryStub
   1224     // clears
   1225     // any pending exceptions - so whenever we'd call this from C++, pending
   1226     // exceptions would be cleared. Preserve this behavior.
   1227     isolate->clear_pending_exception();
   1228   }
   1229 
   1230   DCHECK(mode != SKIP_UNTIL_SEEN);
   1231 
   1232   Handle<Object> no_caller;
   1233   Handle<String> msg = FormatMessage(isolate, template_index, arg0, arg1, arg2);
   1234   return ErrorUtils::Construct(isolate, constructor, constructor, msg, mode,
   1235                                no_caller, false);
   1236 }
   1237 
   1238 }  // namespace internal
   1239 }  // namespace v8
   1240