LCOV - code coverage report
Current view: top level - src - messages.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 434 467 92.9 %
Date: 2017-10-20 Functions: 65 74 87.8 %

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

Generated by: LCOV version 1.10