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-02-19 Functions: 69 75 92.0 %

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

Generated by: LCOV version 1.10