LCOV - code coverage report
Current view: top level - src - messages.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 453 486 93.2 %
Date: 2019-03-21 Functions: 68 75 90.7 %

          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      394610 : MessageLocation::MessageLocation(Handle<Script> script, int start_pos,
      26             :                                  int end_pos)
      27      789220 :     : script_(script), start_pos_(start_pos), end_pos_(end_pos) {}
      28      977160 : 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      977160 :       shared_(shared) {}
      34     8176791 : 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        1343 : void MessageHandler::DefaultMessageReport(Isolate* isolate,
      39             :                                           const MessageLocation* loc,
      40             :                                           Handle<Object> message_obj) {
      41        1343 :   std::unique_ptr<char[]> str = GetLocalizedMessage(isolate, message_obj);
      42        1343 :   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        1343 :     if (data->IsString())
      49           0 :       data_str = Handle<String>::cast(data)->ToCString(DISALLOW_NULLS);
      50        1343 :     PrintF("%s:%i: %s\n", data_str.get() ? data_str.get() : "<unknown>",
      51        1343 :            loc->start_pos(), str.get());
      52             :   }
      53        1343 : }
      54             : 
      55     1359648 : Handle<JSMessageObject> MessageHandler::MakeMessageObject(
      56             :     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     1359648 :   Handle<Script> script_handle = isolate->factory()->empty_script();
      63     1359648 :   if (location != nullptr) {
      64             :     start = location->start_pos();
      65             :     end = location->end_pos();
      66     1355661 :     script_handle = location->script();
      67             :   }
      68             : 
      69             :   Handle<Object> stack_frames_handle = stack_frames.is_null()
      70             :       ? Handle<Object>::cast(factory->undefined_value())
      71     2718844 :       : Handle<Object>::cast(stack_frames);
      72             : 
      73             :   Handle<JSMessageObject> message_obj = factory->NewJSMessageObject(
      74     1359648 :       message, argument, start, end, script_handle, stack_frames_handle);
      75             : 
      76     1359648 :   return message_obj;
      77             : }
      78             : 
      79        8659 : 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        8659 :   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        8019 :     if (isolate->has_pending_exception()) {
      91             :       exception_object = isolate->pending_exception();
      92             :     }
      93             :     Handle<Object> exception(exception_object, isolate);
      94             : 
      95        8019 :     Isolate::ExceptionScope exception_scope(isolate);
      96             :     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        8019 :     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        4051 :       if (argument->IsJSError()) {
     108        3965 :         maybe_stringified = Object::NoSideEffectsToString(isolate, argument);
     109             :       } else {
     110         172 :         v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
     111          86 :         catcher.SetVerbose(false);
     112          86 :         catcher.SetCaptureMessage(false);
     113             : 
     114          86 :         maybe_stringified = Object::ToString(isolate, argument);
     115             :       }
     116             : 
     117        4051 :       if (!maybe_stringified.ToHandle(&stringified)) {
     118             :         DCHECK(isolate->has_pending_exception());
     119             :         isolate->clear_pending_exception();
     120             :         isolate->set_external_caught_exception(false);
     121             :         stringified =
     122          10 :             isolate->factory()->NewStringFromAsciiChecked("exception");
     123             :       }
     124        4051 :       message->set_argument(*stringified);
     125             :     }
     126             : 
     127        8019 :     v8::Local<v8::Value> api_exception_obj = v8::Utils::ToLocal(exception);
     128        8019 :     ReportMessageNoExceptions(isolate, loc, message, api_exception_obj);
     129             :   } else {
     130         640 :     ReportMessageNoExceptions(isolate, loc, message, v8::Local<v8::Value>());
     131             :   }
     132        8659 : }
     133             : 
     134        8659 : 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        8659 :   int error_level = api_message_obj->ErrorLevel();
     139             : 
     140             :   Handle<TemplateList> global_listeners =
     141             :       isolate->factory()->message_listeners();
     142             :   int global_length = global_listeners->length();
     143        8659 :   if (global_length == 0) {
     144        1343 :     DefaultMessageReport(isolate, loc, message);
     145        1343 :     if (isolate->has_scheduled_exception()) {
     146             :       isolate->clear_scheduled_exception();
     147             :     }
     148             :   } else {
     149       14767 :     for (int i = 0; i < global_length; i++) {
     150             :       HandleScope scope(isolate);
     151        7451 :       if (global_listeners->get(i)->IsUndefined(isolate)) continue;
     152             :       FixedArray listener = FixedArray::cast(global_listeners->get(i));
     153             :       Foreign callback_obj = Foreign::cast(listener->get(0));
     154             :       int32_t message_levels =
     155             :           static_cast<int32_t>(Smi::ToInt(listener->get(2)));
     156        7285 :       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        7285 :             isolate, RuntimeCallCounterId::kMessageListenerCallback);
     165             :         // Do not allow exceptions to propagate.
     166       14570 :         v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
     167        7285 :         callback(api_message_obj, callback_data->IsUndefined(isolate)
     168             :                                       ? api_exception_obj
     169        7285 :                                       : v8::Utils::ToLocal(callback_data));
     170             :       }
     171        7285 :       if (isolate->has_scheduled_exception()) {
     172             :         isolate->clear_scheduled_exception();
     173             :       }
     174             :     }
     175             :   }
     176        8659 : }
     177             : 
     178             : 
     179        4236 : Handle<String> MessageHandler::GetMessage(Isolate* isolate,
     180             :                                           Handle<Object> data) {
     181             :   Handle<JSMessageObject> message = Handle<JSMessageObject>::cast(data);
     182             :   Handle<Object> arg = Handle<Object>(message->argument(), isolate);
     183        4236 :   return MessageFormatter::Format(isolate, message->type(), arg);
     184             : }
     185             : 
     186        1343 : std::unique_ptr<char[]> MessageHandler::GetLocalizedMessage(
     187             :     Isolate* isolate, Handle<Object> data) {
     188             :   HandleScope scope(isolate);
     189        4029 :   return GetMessage(isolate, data)->ToCString(DISALLOW_NULLS);
     190             : }
     191             : 
     192             : namespace {
     193             : 
     194         975 : Object EvalFromFunctionName(Isolate* isolate, Handle<Script> script) {
     195         975 :   if (!script->has_eval_from_shared()) {
     196           9 :     return ReadOnlyRoots(isolate).undefined_value();
     197             :   }
     198             : 
     199             :   Handle<SharedFunctionInfo> shared(script->eval_from_shared(), isolate);
     200             :   // Find the name of the function calling eval.
     201         966 :   if (shared->Name()->BooleanValue(isolate)) {
     202         767 :     return shared->Name();
     203             :   }
     204             : 
     205         199 :   return shared->inferred_name();
     206             : }
     207             : 
     208         975 : Object EvalFromScript(Isolate* isolate, Handle<Script> script) {
     209         975 :   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             :                                               isolate);
     215        1932 :   return eval_from_shared->script()->IsScript()
     216         966 :              ? eval_from_shared->script()
     217        1932 :              : ReadOnlyRoots(isolate).undefined_value();
     218             : }
     219             : 
     220         984 : MaybeHandle<String> FormatEvalOrigin(Isolate* isolate, Handle<Script> script) {
     221        1968 :   Handle<Object> sourceURL(script->GetNameOrSourceURL(), isolate);
     222         984 :   if (!sourceURL->IsUndefined(isolate)) {
     223             :     DCHECK(sourceURL->IsString());
     224           9 :     return Handle<String>::cast(sourceURL);
     225             :   }
     226             : 
     227         975 :   IncrementalStringBuilder builder(isolate);
     228             :   builder.AppendCString("eval at ");
     229             : 
     230             :   Handle<Object> eval_from_function_name =
     231         975 :       handle(EvalFromFunctionName(isolate, script), isolate);
     232         975 :   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         975 :       handle(EvalFromScript(isolate, script), isolate);
     244         975 :   if (eval_from_script_obj->IsScript()) {
     245             :     Handle<Script> eval_from_script =
     246             :         Handle<Script>::cast(eval_from_script_obj);
     247             :     builder.AppendCString(" (");
     248         966 :     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             :       Handle<Object> name_obj = handle(eval_from_script->name(), isolate);
     259         894 :       if (eval_from_script->name()->IsString()) {
     260         894 :         builder.AppendString(Handle<String>::cast(name_obj));
     261             : 
     262             :         Script::PositionInfo info;
     263         894 :         if (Script::GetPositionInfo(eval_from_script, script->GetEvalPosition(),
     264             :                                     &info, Script::NO_OFFSET)) {
     265             :           builder.AppendCString(":");
     266             : 
     267             :           Handle<String> str = isolate->factory()->NumberToString(
     268        1788 :               handle(Smi::FromInt(info.line + 1), isolate));
     269         894 :           builder.AppendString(str);
     270             : 
     271             :           builder.AppendCString(":");
     272             : 
     273             :           str = isolate->factory()->NumberToString(
     274        1788 :               handle(Smi::FromInt(info.column + 1), isolate));
     275         894 :           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        1950 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String);
     287         975 :   return result;
     288             : }
     289             : 
     290             : }  // namespace
     291             : 
     292         921 : Handle<Object> StackFrameBase::GetEvalOrigin() {
     293         930 :   if (!HasScript()) return isolate_->factory()->undefined_value();
     294        1824 :   return FormatEvalOrigin(isolate_, GetScript()).ToHandleChecked();
     295             : }
     296             : 
     297       10771 : int StackFrameBase::GetScriptId() const {
     298       10771 :   if (!HasScript()) return kNone;
     299       21542 :   return GetScript()->id();
     300             : }
     301             : 
     302       75307 : bool StackFrameBase::IsEval() {
     303      149096 :   return HasScript() &&
     304      149096 :          GetScript()->compilation_type() == Script::COMPILATION_TYPE_EVAL;
     305             : }
     306             : 
     307         723 : MaybeHandle<String> StackFrameBase::ToString() {
     308         723 :   IncrementalStringBuilder builder(isolate_);
     309         723 :   ToString(builder);
     310         723 :   return builder.Finish();
     311             : }
     312             : 
     313      458691 : void JSStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array,
     314             :                                   int frame_ix) {
     315             :   DCHECK(!array->IsWasmFrame(frame_ix));
     316      458691 :   isolate_ = isolate;
     317      917382 :   receiver_ = handle(array->Receiver(frame_ix), isolate);
     318      917382 :   function_ = handle(array->Function(frame_ix), isolate);
     319      917382 :   code_ = handle(array->Code(frame_ix), isolate);
     320      917382 :   offset_ = array->Offset(frame_ix)->value();
     321             : 
     322      917382 :   const int flags = array->Flags(frame_ix)->value();
     323      458691 :   is_constructor_ = (flags & FrameArray::kIsConstructor) != 0;
     324      458691 :   is_strict_ = (flags & FrameArray::kIsStrict) != 0;
     325      458691 :   is_async_ = (flags & FrameArray::kIsAsync) != 0;
     326      458691 :   is_promise_all_ = (flags & FrameArray::kIsPromiseAll) != 0;
     327      458691 : }
     328             : 
     329           0 : JSStackFrame::JSStackFrame(Isolate* isolate, Handle<Object> receiver,
     330             :                            Handle<JSFunction> function,
     331             :                            Handle<AbstractCode> code, int offset)
     332             :     : StackFrameBase(isolate),
     333             :       receiver_(receiver),
     334             :       function_(function),
     335             :       code_(code),
     336             :       offset_(offset),
     337             :       is_async_(false),
     338             :       is_constructor_(false),
     339           0 :       is_strict_(false) {}
     340             : 
     341       10723 : Handle<Object> JSStackFrame::GetFunction() const {
     342       10723 :   return Handle<Object>::cast(function_);
     343             : }
     344             : 
     345       64835 : Handle<Object> JSStackFrame::GetFileName() {
     346       64853 :   if (!HasScript()) return isolate_->factory()->null_value();
     347      129634 :   return handle(GetScript()->name(), isolate_);
     348             : }
     349             : 
     350      111859 : Handle<Object> JSStackFrame::GetFunctionName() {
     351      111859 :   Handle<String> result = JSFunction::GetName(function_);
     352      111859 :   if (result->length() != 0) return result;
     353             : 
     354       30410 :   if (HasScript() &&
     355       15196 :       GetScript()->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
     356        1834 :     return isolate_->factory()->eval_string();
     357             :   }
     358       28594 :   return isolate_->factory()->null_value();
     359             : }
     360             : 
     361             : namespace {
     362             : 
     363       13861 : bool CheckMethodName(Isolate* isolate, Handle<JSReceiver> receiver,
     364             :                      Handle<Name> name, Handle<JSFunction> fun,
     365             :                      LookupIterator::Configuration config) {
     366             :   LookupIterator iter =
     367       13861 :       LookupIterator::PropertyOrElement(isolate, receiver, name, config);
     368       13861 :   if (iter.state() == LookupIterator::DATA) {
     369       24836 :     return iter.GetDataValue().is_identical_to(fun);
     370        1443 :   } else if (iter.state() == LookupIterator::ACCESSOR) {
     371         387 :     Handle<Object> accessors = iter.GetAccessors();
     372         387 :     if (accessors->IsAccessorPair()) {
     373             :       Handle<AccessorPair> pair = Handle<AccessorPair>::cast(accessors);
     374         639 :       return pair->getter() == *fun || pair->setter() == *fun;
     375             :     }
     376             :   }
     377             :   return false;
     378             : }
     379             : 
     380       69034 : Handle<Object> ScriptNameOrSourceUrl(Handle<Script> script, Isolate* isolate) {
     381             :   Object name_or_url = script->source_url();
     382       69034 :   if (!name_or_url->IsString()) name_or_url = script->name();
     383       69034 :   return handle(name_or_url, isolate);
     384             : }
     385             : 
     386             : }  // namespace
     387             : 
     388       70428 : Handle<Object> JSStackFrame::GetScriptNameOrSourceUrl() {
     389       71910 :   if (!HasScript()) return isolate_->factory()->null_value();
     390       68946 :   return ScriptNameOrSourceUrl(GetScript(), isolate_);
     391             : }
     392             : 
     393        9917 : Handle<Object> JSStackFrame::GetMethodName() {
     394       19834 :   if (receiver_->IsNullOrUndefined(isolate_)) {
     395           0 :     return isolate_->factory()->null_value();
     396             :   }
     397             : 
     398             :   Handle<JSReceiver> receiver;
     399       19834 :   if (!Object::ToObject(isolate_, receiver_).ToHandle(&receiver)) {
     400             :     DCHECK(isolate_->has_pending_exception());
     401           0 :     isolate_->clear_pending_exception();
     402           0 :     isolate_->set_external_caught_exception(false);
     403           0 :     return isolate_->factory()->null_value();
     404             :   }
     405             : 
     406       29751 :   Handle<String> name(function_->shared()->Name(), isolate_);
     407             : 
     408             :   // The static initializer function is not a method, so don't add a
     409             :   // class name, just return the function name.
     410        9917 :   if (name->IsUtf8EqualTo(CStrVector("<static_fields_initializer>"), true)) {
     411          14 :     return name;
     412             :   }
     413             : 
     414             :   // ES2015 gives getters and setters name prefixes which must
     415             :   // be stripped to find the property name.
     416       29637 :   if (name->IsUtf8EqualTo(CStrVector("get "), true) ||
     417       19734 :       name->IsUtf8EqualTo(CStrVector("set "), true)) {
     418          81 :     name = isolate_->factory()->NewProperSubString(name, 4, name->length());
     419             :   }
     420        9903 :   if (CheckMethodName(isolate_, receiver, name, function_,
     421             :                       LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR)) {
     422        8838 :     return name;
     423             :   }
     424             : 
     425        1065 :   HandleScope outer_scope(isolate_);
     426             :   Handle<Object> result;
     427        3795 :   for (PrototypeIterator iter(isolate_, receiver, kStartAtReceiver);
     428        2730 :        !iter.IsAtEnd(); iter.Advance()) {
     429             :     Handle<Object> current = PrototypeIterator::GetCurrent(iter);
     430        2739 :     if (!current->IsJSObject()) break;
     431             :     Handle<JSObject> current_obj = Handle<JSObject>::cast(current);
     432        2739 :     if (current_obj->IsAccessCheckNeeded()) break;
     433             :     Handle<FixedArray> keys =
     434        2739 :         KeyAccumulator::GetOwnEnumPropertyKeys(isolate_, current_obj);
     435       10637 :     for (int i = 0; i < keys->length(); i++) {
     436        3958 :       HandleScope inner_scope(isolate_);
     437        3958 :       if (!keys->get(i)->IsName()) continue;
     438        3958 :       Handle<Name> name_key(Name::cast(keys->get(i)), isolate_);
     439        3958 :       if (!CheckMethodName(isolate_, current_obj, name_key, function_,
     440             :                            LookupIterator::OWN_SKIP_INTERCEPTOR))
     441             :         continue;
     442             :       // Return null in case of duplicates to avoid confusion.
     443         397 :       if (!result.is_null()) return isolate_->factory()->null_value();
     444         379 :       result = inner_scope.CloseAndEscape(name_key);
     445             :     }
     446             :   }
     447             : 
     448        1056 :   if (!result.is_null()) return outer_scope.CloseAndEscape(result);
     449        1372 :   return isolate_->factory()->null_value();
     450             : }
     451             : 
     452       10359 : Handle<Object> JSStackFrame::GetTypeName() {
     453             :   // TODO(jgruber): Check for strict/constructor here as in
     454             :   // CallSitePrototypeGetThis.
     455             : 
     456       20718 :   if (receiver_->IsNullOrUndefined(isolate_)) {
     457          18 :     return isolate_->factory()->null_value();
     458       10341 :   } else if (receiver_->IsJSProxy()) {
     459          18 :     return isolate_->factory()->Proxy_string();
     460             :   }
     461             : 
     462             :   Handle<JSReceiver> receiver;
     463       20664 :   if (!Object::ToObject(isolate_, receiver_).ToHandle(&receiver)) {
     464             :     DCHECK(isolate_->has_pending_exception());
     465           0 :     isolate_->clear_pending_exception();
     466           0 :     isolate_->set_external_caught_exception(false);
     467           0 :     return isolate_->factory()->null_value();
     468             :   }
     469             : 
     470       10332 :   return JSReceiver::GetConstructorName(receiver);
     471             : }
     472             : 
     473      101760 : int JSStackFrame::GetLineNumber() {
     474             :   DCHECK_LE(0, GetPosition());
     475      101760 :   if (HasScript()) return Script::GetLineNumber(GetScript(), GetPosition()) + 1;
     476             :   return kNone;
     477             : }
     478             : 
     479      100117 : int JSStackFrame::GetColumnNumber() {
     480             :   DCHECK_LE(0, GetPosition());
     481      100117 :   if (HasScript()) {
     482      100099 :     return Script::GetColumnNumber(GetScript(), GetPosition()) + 1;
     483             :   }
     484             :   return kNone;
     485             : }
     486             : 
     487          27 : int JSStackFrame::GetPromiseIndex() const {
     488          27 :   return is_promise_all_ ? offset_ : kNone;
     489             : }
     490             : 
     491       91172 : bool JSStackFrame::IsNative() {
     492      180844 :   return HasScript() && GetScript()->type() == Script::TYPE_NATIVE;
     493             : }
     494             : 
     495       91217 : bool JSStackFrame::IsToplevel() {
     496      103058 :   return receiver_->IsJSGlobalProxy() || receiver_->IsNullOrUndefined(isolate_);
     497             : }
     498             : 
     499             : namespace {
     500             : 
     501      140120 : bool IsNonEmptyString(Handle<Object> object) {
     502      267850 :   return (object->IsString() && String::cast(*object)->length() > 0);
     503             : }
     504             : 
     505       60189 : void AppendFileLocation(Isolate* isolate, StackFrameBase* call_site,
     506             :                         IncrementalStringBuilder* builder) {
     507       60189 :   if (call_site->IsNative()) {
     508             :     builder->AppendCString("native");
     509           0 :     return;
     510             :   }
     511             : 
     512       60189 :   Handle<Object> file_name = call_site->GetScriptNameOrSourceUrl();
     513       60189 :   if (!file_name->IsString() && call_site->IsEval()) {
     514         756 :     Handle<Object> eval_origin = call_site->GetEvalOrigin();
     515             :     DCHECK(eval_origin->IsString());
     516         756 :     builder->AppendString(Handle<String>::cast(eval_origin));
     517             :     builder->AppendCString(", ");  // Expecting source position to follow.
     518             :   }
     519             : 
     520       60189 :   if (IsNonEmptyString(file_name)) {
     521       56916 :     builder->AppendString(Handle<String>::cast(file_name));
     522             :   } else {
     523             :     // Source code does not originate from a file and is not native, but we
     524             :     // can still get the source position inside the source string, e.g. in
     525             :     // an eval string.
     526             :     builder->AppendCString("<anonymous>");
     527             :   }
     528             : 
     529       60189 :   int line_number = call_site->GetLineNumber();
     530       60189 :   if (line_number != StackFrameBase::kNone) {
     531             :     builder->AppendCharacter(':');
     532             :     Handle<String> line_string = isolate->factory()->NumberToString(
     533      117414 :         handle(Smi::FromInt(line_number), isolate), isolate);
     534       58707 :     builder->AppendString(line_string);
     535             : 
     536       58707 :     int column_number = call_site->GetColumnNumber();
     537       58707 :     if (column_number != StackFrameBase::kNone) {
     538             :       builder->AppendCharacter(':');
     539             :       Handle<String> column_string = isolate->factory()->NumberToString(
     540       58707 :           handle(Smi::FromInt(column_number), isolate), isolate);
     541       58707 :       builder->AppendString(column_string);
     542             :     }
     543             :   }
     544             : }
     545             : 
     546        9732 : int StringIndexOf(Isolate* isolate, Handle<String> subject,
     547             :                   Handle<String> pattern) {
     548        9732 :   if (pattern->length() > subject->length()) return -1;
     549        6460 :   return String::IndexOf(isolate, subject, pattern, 0);
     550             : }
     551             : 
     552             : // Returns true iff
     553             : // 1. the subject ends with '.' + pattern, or
     554             : // 2. subject == pattern.
     555        9123 : bool StringEndsWithMethodName(Isolate* isolate, Handle<String> subject,
     556             :                               Handle<String> pattern) {
     557        9123 :   if (String::Equals(isolate, subject, pattern)) return true;
     558             : 
     559         379 :   FlatStringReader subject_reader(isolate, String::Flatten(isolate, subject));
     560         379 :   FlatStringReader pattern_reader(isolate, String::Flatten(isolate, pattern));
     561             : 
     562         379 :   int pattern_index = pattern_reader.length() - 1;
     563         379 :   int subject_index = subject_reader.length() - 1;
     564        6841 :   for (int i = 0; i <= pattern_reader.length(); i++) {  // Iterate over len + 1.
     565        3402 :     if (subject_index < 0) {
     566             :       return false;
     567             :     }
     568             : 
     569             :     const uc32 subject_char = subject_reader.Get(subject_index);
     570        3402 :     if (i == pattern_reader.length()) {
     571         271 :       if (subject_char != '.') return false;
     572        3131 :     } else if (subject_char != pattern_reader.Get(pattern_index)) {
     573             :       return false;
     574             :     }
     575             : 
     576        3231 :     pattern_index--;
     577        3231 :     subject_index--;
     578             :   }
     579             : 
     580             :   return true;
     581             : }
     582             : 
     583        9827 : void AppendMethodCall(Isolate* isolate, JSStackFrame* call_site,
     584             :                       IncrementalStringBuilder* builder) {
     585        9827 :   Handle<Object> type_name = call_site->GetTypeName();
     586        9827 :   Handle<Object> method_name = call_site->GetMethodName();
     587        9827 :   Handle<Object> function_name = call_site->GetFunctionName();
     588             : 
     589        9827 :   if (IsNonEmptyString(function_name)) {
     590        9732 :     Handle<String> function_string = Handle<String>::cast(function_name);
     591        9732 :     if (IsNonEmptyString(type_name)) {
     592        9732 :       Handle<String> type_string = Handle<String>::cast(type_name);
     593             :       bool starts_with_type_name =
     594        9732 :           (StringIndexOf(isolate, function_string, type_string) == 0);
     595        9732 :       if (!starts_with_type_name) {
     596        9664 :         builder->AppendString(type_string);
     597             :         builder->AppendCharacter('.');
     598             :       }
     599             :     }
     600        9732 :     builder->AppendString(function_string);
     601             : 
     602        9732 :     if (IsNonEmptyString(method_name)) {
     603        9123 :       Handle<String> method_string = Handle<String>::cast(method_name);
     604        9123 :       if (!StringEndsWithMethodName(isolate, function_string, method_string)) {
     605             :         builder->AppendCString(" [as ");
     606         171 :         builder->AppendString(method_string);
     607             :         builder->AppendCharacter(']');
     608             :       }
     609             :     }
     610             :   } else {
     611          95 :     if (IsNonEmptyString(type_name)) {
     612          95 :       builder->AppendString(Handle<String>::cast(type_name));
     613             :       builder->AppendCharacter('.');
     614             :     }
     615          95 :     if (IsNonEmptyString(method_name)) {
     616          36 :       builder->AppendString(Handle<String>::cast(method_name));
     617             :     } else {
     618             :       builder->AppendCString("<anonymous>");
     619             :     }
     620             :   }
     621        9827 : }
     622             : 
     623             : }  // namespace
     624             : 
     625       60146 : void JSStackFrame::ToString(IncrementalStringBuilder& builder) {
     626       60146 :   Handle<Object> function_name = GetFunctionName();
     627             : 
     628       60146 :   const bool is_toplevel = IsToplevel();
     629       60146 :   const bool is_async = IsAsync();
     630       60146 :   const bool is_promise_all = IsPromiseAll();
     631       60146 :   const bool is_constructor = IsConstructor();
     632       60146 :   const bool is_method_call = !(is_toplevel || is_constructor);
     633             : 
     634       60146 :   if (is_async) {
     635             :     builder.AppendCString("async ");
     636             :   }
     637       60146 :   if (is_promise_all) {
     638             :     // For `Promise.all(iterable)` frames we interpret the {offset_}
     639             :     // as the element index into `iterable` where the error occurred.
     640             :     builder.AppendCString("Promise.all (index ");
     641          45 :     Handle<String> index_string = isolate_->factory()->NumberToString(
     642          90 :         handle(Smi::FromInt(offset_), isolate_), isolate_);
     643          45 :     builder.AppendString(index_string);
     644             :     builder.AppendCString(")");
     645             :     return;
     646             :   }
     647       60101 :   if (is_method_call) {
     648        9827 :     AppendMethodCall(isolate_, this, &builder);
     649       50274 :   } else if (is_constructor) {
     650             :     builder.AppendCString("new ");
     651         712 :     if (IsNonEmptyString(function_name)) {
     652         712 :       builder.AppendString(Handle<String>::cast(function_name));
     653             :     } else {
     654             :       builder.AppendCString("<anonymous>");
     655             :     }
     656       49562 :   } else if (IsNonEmptyString(function_name)) {
     657       40296 :     builder.AppendString(Handle<String>::cast(function_name));
     658             :   } else {
     659        9266 :     AppendFileLocation(isolate_, this, &builder);
     660        9266 :     return;
     661             :   }
     662             : 
     663             :   builder.AppendCString(" (");
     664       50835 :   AppendFileLocation(isolate_, this, &builder);
     665             :   builder.AppendCString(")");
     666             : 
     667             :   return;
     668             : }
     669             : 
     670      400718 : int JSStackFrame::GetPosition() const { return code_->SourcePosition(offset_); }
     671             : 
     672      529509 : bool JSStackFrame::HasScript() const {
     673     1059018 :   return function_->shared()->script()->IsScript();
     674             : }
     675             : 
     676      523446 : Handle<Script> JSStackFrame::GetScript() const {
     677     1570338 :   return handle(Script::cast(function_->shared()->script()), isolate_);
     678             : }
     679             : 
     680        5996 : void WasmStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array,
     681             :                                     int frame_ix) {
     682             :   // This function is called for compiled and interpreted wasm frames, and for
     683             :   // asm.js->wasm frames.
     684             :   DCHECK(array->IsWasmFrame(frame_ix) ||
     685             :          array->IsWasmInterpretedFrame(frame_ix) ||
     686             :          array->IsAsmJsWasmFrame(frame_ix));
     687        5996 :   isolate_ = isolate;
     688       11992 :   wasm_instance_ = handle(array->WasmInstance(frame_ix), isolate);
     689       11992 :   wasm_func_index_ = array->WasmFunctionIndex(frame_ix)->value();
     690       11992 :   if (array->IsWasmInterpretedFrame(frame_ix)) {
     691        3224 :     code_ = nullptr;
     692             :   } else {
     693             :     code_ = reinterpret_cast<wasm::WasmCode*>(
     694        5544 :         array->WasmCodeObject(frame_ix)->foreign_address());
     695             :   }
     696       11992 :   offset_ = array->Offset(frame_ix)->value();
     697        5996 : }
     698             : 
     699           0 : Handle<Object> WasmStackFrame::GetReceiver() const { return wasm_instance_; }
     700             : 
     701           0 : Handle<Object> WasmStackFrame::GetFunction() const {
     702           0 :   return handle(Smi::FromInt(wasm_func_index_), isolate_);
     703             : }
     704             : 
     705         908 : Handle<Object> WasmStackFrame::GetFunctionName() {
     706             :   Handle<Object> name;
     707             :   Handle<WasmModuleObject> module_object(wasm_instance_->module_object(),
     708         908 :                                          isolate_);
     709        1816 :   if (!WasmModuleObject::GetFunctionNameOrNull(isolate_, module_object,
     710         908 :                                                wasm_func_index_)
     711             :            .ToHandle(&name)) {
     712          16 :     name = isolate_->factory()->null_value();
     713             :   }
     714         908 :   return name;
     715             : }
     716             : 
     717         596 : void WasmStackFrame::ToString(IncrementalStringBuilder& builder) {
     718             :   Handle<WasmModuleObject> module_object(wasm_instance_->module_object(),
     719         596 :                                          isolate_);
     720             :   MaybeHandle<String> module_name =
     721         596 :       WasmModuleObject::GetModuleNameOrNull(isolate_, module_object);
     722             :   MaybeHandle<String> function_name = WasmModuleObject::GetFunctionNameOrNull(
     723         596 :       isolate_, module_object, wasm_func_index_);
     724         596 :   bool has_name = !module_name.is_null() || !function_name.is_null();
     725         596 :   if (has_name) {
     726         568 :     if (module_name.is_null()) {
     727         544 :       builder.AppendString(function_name.ToHandleChecked());
     728             :     } else {
     729          24 :       builder.AppendString(module_name.ToHandleChecked());
     730          24 :       if (!function_name.is_null()) {
     731             :         builder.AppendCString(".");
     732          12 :         builder.AppendString(function_name.ToHandleChecked());
     733             :       }
     734             :     }
     735             :     builder.AppendCString(" (");
     736             :   }
     737             : 
     738             :   builder.AppendCString("wasm-function[");
     739             : 
     740             :   char buffer[16];
     741         596 :   SNPrintF(ArrayVector(buffer), "%u]", wasm_func_index_);
     742             :   builder.AppendCString(buffer);
     743             : 
     744         596 :   SNPrintF(ArrayVector(buffer), ":%d", GetPosition());
     745             :   builder.AppendCString(buffer);
     746             : 
     747         596 :   if (has_name) builder.AppendCString(")");
     748             : 
     749         596 :   return;
     750             : }
     751             : 
     752        1240 : int WasmStackFrame::GetPosition() const {
     753             :   return IsInterpreted()
     754             :              ? offset_
     755             :              : FrameSummary::WasmCompiledFrameSummary::GetWasmSourcePosition(
     756        1240 :                    code_, offset_);
     757             : }
     758             : 
     759           0 : Handle<Object> WasmStackFrame::Null() const {
     760         960 :   return isolate_->factory()->null_value();
     761             : }
     762             : 
     763        1016 : bool WasmStackFrame::HasScript() const { return true; }
     764             : 
     765        1016 : Handle<Script> WasmStackFrame::GetScript() const {
     766        2032 :   return handle(wasm_instance_->module_object()->script(), isolate_);
     767             : }
     768             : 
     769        1256 : void AsmJsWasmStackFrame::FromFrameArray(Isolate* isolate,
     770             :                                          Handle<FrameArray> array,
     771             :                                          int frame_ix) {
     772             :   DCHECK(array->IsAsmJsWasmFrame(frame_ix));
     773        1256 :   WasmStackFrame::FromFrameArray(isolate, array, frame_ix);
     774             :   is_at_number_conversion_ =
     775        2512 :       array->Flags(frame_ix)->value() & FrameArray::kAsmJsAtNumberConversion;
     776        1256 : }
     777             : 
     778         208 : Handle<Object> AsmJsWasmStackFrame::GetReceiver() const {
     779         208 :   return isolate_->global_proxy();
     780             : }
     781             : 
     782           0 : Handle<Object> AsmJsWasmStackFrame::GetFunction() const {
     783             :   // TODO(clemensh): Return lazily created JSFunction.
     784           0 :   return Null();
     785             : }
     786             : 
     787         224 : Handle<Object> AsmJsWasmStackFrame::GetFileName() {
     788         224 :   Handle<Script> script(wasm_instance_->module_object()->script(), isolate_);
     789             :   DCHECK(script->IsUserJavaScript());
     790         448 :   return handle(script->name(), isolate_);
     791             : }
     792             : 
     793          88 : Handle<Object> AsmJsWasmStackFrame::GetScriptNameOrSourceUrl() {
     794          88 :   Handle<Script> script(wasm_instance_->module_object()->script(), isolate_);
     795             :   DCHECK_EQ(Script::TYPE_NORMAL, script->type());
     796          88 :   return ScriptNameOrSourceUrl(script, isolate_);
     797             : }
     798             : 
     799         656 : int AsmJsWasmStackFrame::GetPosition() const {
     800             :   DCHECK_LE(0, offset_);
     801             :   int byte_offset =
     802         656 :       FrameSummary::WasmCompiledFrameSummary::GetWasmSourcePosition(code_,
     803        1312 :                                                                     offset_);
     804             :   Handle<WasmModuleObject> module_object(wasm_instance_->module_object(),
     805         656 :                                          isolate_);
     806             :   DCHECK_LE(0, byte_offset);
     807         656 :   return WasmModuleObject::GetSourcePosition(module_object, wasm_func_index_,
     808             :                                              static_cast<uint32_t>(byte_offset),
     809        1312 :                                              is_at_number_conversion_);
     810             : }
     811             : 
     812         312 : int AsmJsWasmStackFrame::GetLineNumber() {
     813             :   DCHECK_LE(0, GetPosition());
     814         312 :   Handle<Script> script(wasm_instance_->module_object()->script(), isolate_);
     815             :   DCHECK(script->IsUserJavaScript());
     816         312 :   return Script::GetLineNumber(script, GetPosition()) + 1;
     817             : }
     818             : 
     819         344 : int AsmJsWasmStackFrame::GetColumnNumber() {
     820             :   DCHECK_LE(0, GetPosition());
     821         344 :   Handle<Script> script(wasm_instance_->module_object()->script(), isolate_);
     822             :   DCHECK(script->IsUserJavaScript());
     823         344 :   return Script::GetColumnNumber(script, GetPosition()) + 1;
     824             : }
     825             : 
     826          88 : void AsmJsWasmStackFrame::ToString(IncrementalStringBuilder& builder) {
     827             :   // The string should look exactly as the respective javascript frame string.
     828             :   // Keep this method in line to
     829             :   // JSStackFrame::ToString(IncrementalStringBuilder&).
     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;
     842             : }
     843             : 
     844      318856 : FrameArrayIterator::FrameArrayIterator(Isolate* isolate,
     845             :                                        Handle<FrameArray> array, int frame_ix)
     846      647493 :     : isolate_(isolate), array_(array), frame_ix_(frame_ix) {}
     847             : 
     848           0 : bool FrameArrayIterator::HasFrame() const {
     849       69888 :   return (frame_ix_ < array_->FrameCount());
     850             : }
     851             : 
     852       60107 : void FrameArrayIterator::Advance() { frame_ix_++; }
     853             : 
     854      464687 : StackFrameBase* FrameArrayIterator::Frame() {
     855             :   DCHECK(HasFrame());
     856     1394061 :   const int flags = array_->Flags(frame_ix_)->value();
     857             :   int flag_mask = FrameArray::kIsWasmFrame |
     858             :                   FrameArray::kIsWasmInterpretedFrame |
     859             :                   FrameArray::kIsAsmJsWasmFrame;
     860      464687 :   switch (flags & flag_mask) {
     861             :     case 0:
     862             :       // JavaScript Frame.
     863      458691 :       js_frame_.FromFrameArray(isolate_, array_, frame_ix_);
     864      458691 :       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       49063 : MaybeHandle<Object> ConstructCallSite(Isolate* isolate,
     882             :                                       Handle<FrameArray> frame_array,
     883             :                                       int frame_index) {
     884             :   Handle<JSFunction> target =
     885      147189 :       handle(isolate->native_context()->callsite_function(), isolate);
     886             : 
     887             :   Handle<JSObject> obj;
     888       98126 :   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       98126 :   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       98126 :   RETURN_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
     900             :                                    obj, key, value, DONT_ENUM),
     901             :                       Object);
     902             : 
     903       49063 :   return obj;
     904             : }
     905             : 
     906             : // Convert the raw frames as written by Isolate::CaptureSimpleStackTrace into
     907             : // a JSArray of JSCallSite objects.
     908        5432 : MaybeHandle<JSArray> GetStackFrames(Isolate* isolate,
     909             :                                     Handle<FrameArray> elems) {
     910             :   const int frame_count = elems->FrameCount();
     911             : 
     912        5432 :   Handle<FixedArray> frames = isolate->factory()->NewFixedArray(frame_count);
     913      103558 :   for (int i = 0; i < frame_count; i++) {
     914             :     Handle<Object> site;
     915       98126 :     ASSIGN_RETURN_ON_EXCEPTION(isolate, site,
     916             :                                ConstructCallSite(isolate, elems, i), JSArray);
     917       49063 :     frames->set(i, *site);
     918             :   }
     919             : 
     920        5432 :   return isolate->factory()->NewJSArrayWithElements(frames);
     921             : }
     922             : 
     923        9781 : MaybeHandle<Object> AppendErrorString(Isolate* isolate, Handle<Object> error,
     924             :                                       IncrementalStringBuilder* builder) {
     925             :   MaybeHandle<String> err_str =
     926        9781 :       ErrorUtils::ToString(isolate, Handle<Object>::cast(error));
     927        9781 :   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             :     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             :       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        9781 :     builder->AppendString(err_str.ToHandleChecked());
     952             :   }
     953             : 
     954        9781 :   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       15213 : MaybeHandle<Object> ErrorUtils::FormatStackTrace(Isolate* isolate,
     976             :                                                  Handle<JSObject> error,
     977             :                                                  Handle<Object> raw_stack) {
     978             :   DCHECK(raw_stack->IsJSArray());
     979             :   Handle<JSArray> raw_stack_array = Handle<JSArray>::cast(raw_stack);
     980             : 
     981             :   DCHECK(raw_stack_array->elements()->IsFixedArray());
     982             :   Handle<FrameArray> elems(FrameArray::cast(raw_stack_array->elements()),
     983             :                            isolate);
     984             : 
     985             :   const bool in_recursion = isolate->formatting_stack_trace();
     986       15213 :   if (!in_recursion) {
     987       15186 :     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       15174 :       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       30348 :       ASSIGN_RETURN_ON_EXCEPTION(
    1010             :           isolate, prepare_stack_trace,
    1011             :           JSFunction::GetProperty(isolate, global_error, "prepareStackTrace"),
    1012             :           Object);
    1013             : 
    1014       15174 :       if (prepare_stack_trace->IsJSFunction()) {
    1015             :         PrepareStackTraceScope scope(isolate);
    1016             : 
    1017        5420 :         isolate->CountUsage(v8::Isolate::kErrorPrepareStackTrace);
    1018             : 
    1019             :         Handle<JSArray> sites;
    1020       10840 :         ASSIGN_RETURN_ON_EXCEPTION(isolate, sites,
    1021             :                                    GetStackFrames(isolate, elems), Object);
    1022             : 
    1023             :         const int argc = 2;
    1024             :         ScopedVector<Handle<Object>> argv(argc);
    1025        5420 :         argv[0] = error;
    1026        5420 :         argv[1] = sites;
    1027             : 
    1028             :         Handle<Object> result;
    1029             : 
    1030       10840 :         ASSIGN_RETURN_ON_EXCEPTION(
    1031             :             isolate, result,
    1032             :             Execution::Call(isolate, prepare_stack_trace, global_error, argc,
    1033             :                             argv.start()),
    1034             :             Object);
    1035             : 
    1036        5310 :         return result;
    1037             :       }
    1038             :     }
    1039             :   }
    1040             : 
    1041             :   // Otherwise, run our internal formatting logic.
    1042             : 
    1043        9781 :   IncrementalStringBuilder builder(isolate);
    1044             : 
    1045       19562 :   RETURN_ON_EXCEPTION(isolate, AppendErrorString(isolate, error, &builder),
    1046             :                       Object);
    1047             : 
    1048       69888 :   for (FrameArrayIterator it(isolate, elems); it.HasFrame(); it.Advance()) {
    1049             :     builder.AppendCString("\n    at ");
    1050             : 
    1051       60107 :     StackFrameBase* frame = it.Frame();
    1052       60107 :     frame->ToString(builder);
    1053       60107 :     if (isolate->has_pending_exception()) {
    1054             :       // CallSite.toString threw. Parts of the current frame might have been
    1055             :       // stringified already regardless. Still, try to append a string
    1056             :       // representation of the thrown exception.
    1057             : 
    1058             :       Handle<Object> pending_exception =
    1059           0 :           handle(isolate->pending_exception(), isolate);
    1060             :       isolate->clear_pending_exception();
    1061             :       isolate->set_external_caught_exception(false);
    1062             : 
    1063             :       MaybeHandle<String> exception_string =
    1064           0 :           ErrorUtils::ToString(isolate, pending_exception);
    1065           0 :       if (exception_string.is_null()) {
    1066             :         // Formatting the thrown exception threw again, give up.
    1067             : 
    1068             :         builder.AppendCString("<error>");
    1069             :       } else {
    1070             :         // Formatted thrown exception successfully, append it.
    1071             :         builder.AppendCString("<error: ");
    1072           0 :         builder.AppendString(exception_string.ToHandleChecked());
    1073             :         builder.AppendCString("<error>");
    1074             :       }
    1075             :     }
    1076             :   }
    1077             : 
    1078        9781 :   return builder.Finish();
    1079             : }
    1080             : 
    1081        7290 : Handle<String> MessageFormatter::Format(Isolate* isolate, MessageTemplate index,
    1082             :                                         Handle<Object> arg) {
    1083             :   Factory* factory = isolate->factory();
    1084        7290 :   Handle<String> result_string = Object::NoSideEffectsToString(isolate, arg);
    1085             :   MaybeHandle<String> maybe_result_string = MessageFormatter::Format(
    1086             :       isolate, index, result_string, factory->empty_string(),
    1087        7290 :       factory->empty_string());
    1088        7290 :   if (!maybe_result_string.ToHandle(&result_string)) {
    1089             :     DCHECK(isolate->has_pending_exception());
    1090             :     isolate->clear_pending_exception();
    1091           0 :     return factory->InternalizeOneByteString(StaticCharVector("<error>"));
    1092             :   }
    1093             :   // A string that has been obtained from JS code in this way is
    1094             :   // likely to be a complicated ConsString of some sort.  We flatten it
    1095             :   // here to improve the efficiency of converting it to a C string and
    1096             :   // other operations that are likely to take place (see GetLocalizedMessage
    1097             :   // for example).
    1098        7290 :   return String::Flatten(isolate, result_string);
    1099             : }
    1100             : 
    1101     1208034 : const char* MessageFormatter::TemplateString(MessageTemplate index) {
    1102     1208034 :   switch (index) {
    1103             : #define CASE(NAME, STRING)       \
    1104             :   case MessageTemplate::k##NAME: \
    1105             :     return STRING;
    1106          60 :     MESSAGE_TEMPLATES(CASE)
    1107             : #undef CASE
    1108             :     case MessageTemplate::kLastMessage:
    1109             :     default:
    1110           0 :       return nullptr;
    1111             :   }
    1112             : }
    1113             : 
    1114     1159196 : MaybeHandle<String> MessageFormatter::Format(Isolate* isolate,
    1115             :                                              MessageTemplate index,
    1116             :                                              Handle<String> arg0,
    1117             :                                              Handle<String> arg1,
    1118             :                                              Handle<String> arg2) {
    1119     1159196 :   const char* template_string = TemplateString(index);
    1120     1159196 :   if (template_string == nullptr) {
    1121           0 :     isolate->ThrowIllegalOperation();
    1122           0 :     return MaybeHandle<String>();
    1123             :   }
    1124             : 
    1125     1159196 :   IncrementalStringBuilder builder(isolate);
    1126             : 
    1127             :   unsigned int i = 0;
    1128     1159196 :   Handle<String> args[] = {arg0, arg1, arg2};
    1129    82836106 :   for (const char* c = template_string; *c != '\0'; c++) {
    1130    40838455 :     if (*c == '%') {
    1131             :       // %% results in verbatim %.
    1132      751203 :       if (*(c + 1) == '%') {
    1133           0 :         c++;
    1134             :         builder.AppendCharacter('%');
    1135             :       } else {
    1136             :         DCHECK(i < arraysize(args));
    1137      751203 :         Handle<String> arg = args[i++];
    1138      751203 :         builder.AppendString(arg);
    1139             :       }
    1140             :     } else {
    1141    40087252 :       builder.AppendCharacter(*c);
    1142             :     }
    1143             :   }
    1144             : 
    1145     1159196 :   return builder.Finish();
    1146             : }
    1147             : 
    1148     1253559 : MaybeHandle<Object> ErrorUtils::Construct(
    1149             :     Isolate* isolate, Handle<JSFunction> target, Handle<Object> new_target,
    1150             :     Handle<Object> message, FrameSkipMode mode, Handle<Object> caller,
    1151             :     bool suppress_detailed_trace) {
    1152             :   // 1. If NewTarget is undefined, let newTarget be the active function object,
    1153             :   // else let newTarget be NewTarget.
    1154             : 
    1155             :   Handle<JSReceiver> new_target_recv =
    1156             :       new_target->IsJSReceiver() ? Handle<JSReceiver>::cast(new_target)
    1157     1253559 :                                  : Handle<JSReceiver>::cast(target);
    1158             : 
    1159             :   // 2. Let O be ? OrdinaryCreateFromConstructor(newTarget, "%ErrorPrototype%",
    1160             :   //    « [[ErrorData]] »).
    1161             :   Handle<JSObject> err;
    1162     2507118 :   ASSIGN_RETURN_ON_EXCEPTION(
    1163             :       isolate, err,
    1164             :       JSObject::New(target, new_target_recv, Handle<AllocationSite>::null()),
    1165             :       Object);
    1166             : 
    1167             :   // 3. If message is not undefined, then
    1168             :   //  a. Let msg be ? ToString(message).
    1169             :   //  b. Let msgDesc be the PropertyDescriptor{[[Value]]: msg, [[Writable]]:
    1170             :   //     true, [[Enumerable]]: false, [[Configurable]]: true}.
    1171             :   //  c. Perform ! DefinePropertyOrThrow(O, "message", msgDesc).
    1172             :   // 4. Return O.
    1173             : 
    1174     1253559 :   if (!message->IsUndefined(isolate)) {
    1175             :     Handle<String> msg_string;
    1176     2483564 :     ASSIGN_RETURN_ON_EXCEPTION(isolate, msg_string,
    1177             :                                Object::ToString(isolate, message), Object);
    1178     2483546 :     RETURN_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
    1179             :                                      err, isolate->factory()->message_string(),
    1180             :                                      msg_string, DONT_ENUM),
    1181             :                         Object);
    1182             :   }
    1183             : 
    1184             :   // Optionally capture a more detailed stack trace for the message.
    1185     1253550 :   if (!suppress_detailed_trace) {
    1186     2410270 :     RETURN_ON_EXCEPTION(isolate, isolate->CaptureAndSetDetailedStackTrace(err),
    1187             :                         Object);
    1188             :   }
    1189             : 
    1190             :   // Capture a simple stack trace for the stack property.
    1191     2507100 :   RETURN_ON_EXCEPTION(isolate,
    1192             :                       isolate->CaptureAndSetSimpleStackTrace(err, mode, caller),
    1193             :                       Object);
    1194             : 
    1195     1253550 :   return err;
    1196             : }
    1197             : 
    1198             : namespace {
    1199             : 
    1200      609597 : MaybeHandle<String> GetStringPropertyOrDefault(Isolate* isolate,
    1201             :                                                Handle<JSReceiver> recv,
    1202             :                                                Handle<String> key,
    1203             :                                                Handle<String> default_str) {
    1204             :   Handle<Object> obj;
    1205     1219194 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, obj,
    1206             :                              JSObject::GetProperty(isolate, recv, key), String);
    1207             : 
    1208             :   Handle<String> str;
    1209      603302 :   if (obj->IsUndefined(isolate)) {
    1210         162 :     str = default_str;
    1211             :   } else {
    1212     1206280 :     ASSIGN_RETURN_ON_EXCEPTION(isolate, str, Object::ToString(isolate, obj),
    1213             :                                String);
    1214             :   }
    1215             : 
    1216      595427 :   return str;
    1217             : }
    1218             : 
    1219             : }  // namespace
    1220             : 
    1221             : // ES6 section 19.5.3.4 Error.prototype.toString ( )
    1222      308934 : MaybeHandle<String> ErrorUtils::ToString(Isolate* isolate,
    1223             :                                          Handle<Object> receiver) {
    1224             :   // 1. Let O be the this value.
    1225             :   // 2. If Type(O) is not Object, throw a TypeError exception.
    1226      308934 :   if (!receiver->IsJSReceiver()) {
    1227             :     return isolate->Throw<String>(isolate->factory()->NewTypeError(
    1228             :         MessageTemplate::kIncompatibleMethodReceiver,
    1229             :         isolate->factory()->NewStringFromAsciiChecked(
    1230             :             "Error.prototype.toString"),
    1231         594 :         receiver));
    1232             :   }
    1233      308736 :   Handle<JSReceiver> recv = Handle<JSReceiver>::cast(receiver);
    1234             : 
    1235             :   // 3. Let name be ? Get(O, "name").
    1236             :   // 4. If name is undefined, let name be "Error"; otherwise let name be
    1237             :   // ? ToString(name).
    1238      308736 :   Handle<String> name_key = isolate->factory()->name_string();
    1239      308736 :   Handle<String> name_default = isolate->factory()->Error_string();
    1240             :   Handle<String> name;
    1241      617472 :   ASSIGN_RETURN_ON_EXCEPTION(
    1242             :       isolate, name,
    1243             :       GetStringPropertyOrDefault(isolate, recv, name_key, name_default),
    1244             :       String);
    1245             : 
    1246             :   // 5. Let msg be ? Get(O, "message").
    1247             :   // 6. If msg is undefined, let msg be the empty String; otherwise let msg be
    1248             :   // ? ToString(msg).
    1249      300861 :   Handle<String> msg_key = isolate->factory()->message_string();
    1250      300861 :   Handle<String> msg_default = isolate->factory()->empty_string();
    1251             :   Handle<String> msg;
    1252      601722 :   ASSIGN_RETURN_ON_EXCEPTION(
    1253             :       isolate, msg,
    1254             :       GetStringPropertyOrDefault(isolate, recv, msg_key, msg_default), String);
    1255             : 
    1256             :   // 7. If name is the empty String, return msg.
    1257             :   // 8. If msg is the empty String, return name.
    1258      294566 :   if (name->length() == 0) return msg;
    1259      294503 :   if (msg->length() == 0) return name;
    1260             : 
    1261             :   // 9. Return the result of concatenating name, the code unit 0x003A (COLON),
    1262             :   // the code unit 0x0020 (SPACE), and msg.
    1263      291204 :   IncrementalStringBuilder builder(isolate);
    1264      291204 :   builder.AppendString(name);
    1265             :   builder.AppendCString(": ");
    1266      291204 :   builder.AppendString(msg);
    1267             : 
    1268             :   Handle<String> result;
    1269      582408 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String);
    1270      291204 :   return result;
    1271             : }
    1272             : 
    1273             : namespace {
    1274             : 
    1275     1151901 : Handle<String> DoFormatMessage(Isolate* isolate, MessageTemplate index,
    1276             :                                Handle<Object> arg0, Handle<Object> arg1,
    1277             :                                Handle<Object> arg2) {
    1278     1151901 :   Handle<String> arg0_str = Object::NoSideEffectsToString(isolate, arg0);
    1279     1151901 :   Handle<String> arg1_str = Object::NoSideEffectsToString(isolate, arg1);
    1280     1151901 :   Handle<String> arg2_str = Object::NoSideEffectsToString(isolate, arg2);
    1281             : 
    1282     2303802 :   isolate->native_context()->IncrementErrorsThrown();
    1283             : 
    1284             :   Handle<String> msg;
    1285     2303802 :   if (!MessageFormatter::Format(isolate, index, arg0_str, arg1_str, arg2_str)
    1286             :            .ToHandle(&msg)) {
    1287             :     DCHECK(isolate->has_pending_exception());
    1288             :     isolate->clear_pending_exception();
    1289             :     isolate->set_external_caught_exception(false);
    1290          18 :     return isolate->factory()->NewStringFromAsciiChecked("<error>");
    1291             :   }
    1292             : 
    1293     1151883 :   return msg;
    1294             : }
    1295             : 
    1296             : }  // namespace
    1297             : 
    1298             : // static
    1299     1151901 : MaybeHandle<Object> ErrorUtils::MakeGenericError(
    1300             :     Isolate* isolate, Handle<JSFunction> constructor, MessageTemplate index,
    1301             :     Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg2,
    1302             :     FrameSkipMode mode) {
    1303     1151901 :   if (FLAG_clear_exceptions_on_js_entry) {
    1304             :     // This function used to be implemented in JavaScript, and JSEntry
    1305             :     // clears any pending exceptions - so whenever we'd call this from C++,
    1306             :     // pending exceptions would be cleared. Preserve this behavior.
    1307             :     isolate->clear_pending_exception();
    1308             :   }
    1309             : 
    1310             :   DCHECK(mode != SKIP_UNTIL_SEEN);
    1311             : 
    1312             :   Handle<Object> no_caller;
    1313     1151901 :   Handle<String> msg = DoFormatMessage(isolate, index, arg0, arg1, arg2);
    1314             :   return ErrorUtils::Construct(isolate, constructor, constructor, msg, mode,
    1315     1151901 :                                no_caller, false);
    1316             : }
    1317             : 
    1318             : }  // namespace internal
    1319      120216 : }  // namespace v8

Generated by: LCOV version 1.10