LCOV - code coverage report
Current view: top level - src - messages.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 422 445 94.8 %
Date: 2017-04-26 Functions: 66 74 89.2 %

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

Generated by: LCOV version 1.10