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