LCOV - code coverage report
Current view: top level - src - messages.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 479 517 92.6 %
Date: 2019-01-20 Functions: 68 74 91.9 %

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

Generated by: LCOV version 1.10