Skip to content

Commit bfd8265

Browse files
alexkozyevanlucas
authored andcommitted
inspector: add support for uncaught exception
To output exception in DevTools console method exceptionThrown should be called on uncaught exception on V8Inspector object. Additionally we need to wait disconnect to provide user way to inspect exception. PR-URL: #8043 Reviewed-By: bnoordhuis - Ben Noordhuis <[email protected]> Reviewed-By: jasnell - James M Snell <[email protected]> Reviewed-By: ofrobots - Ali Ijaz Sheikh <[email protected]>
1 parent 31653a5 commit bfd8265

File tree

3 files changed

+87
-14
lines changed

3 files changed

+87
-14
lines changed

src/inspector_agent.cc

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "platform/v8_inspector/public/V8Inspector.h"
1414
#include "platform/v8_inspector/public/V8InspectorClient.h"
1515
#include "platform/v8_inspector/public/V8InspectorSession.h"
16+
#include "platform/v8_inspector/public/V8StackTrace.h"
1617
#include "platform/inspector_protocol/FrontendChannel.h"
1718
#include "platform/inspector_protocol/String16.h"
1819
#include "platform/inspector_protocol/Values.h"
@@ -175,6 +176,9 @@ class AgentImpl {
175176
bool IsConnected() { return state_ == State::kConnected; }
176177
void WaitForDisconnect();
177178

179+
void FatalException(v8::Local<v8::Value> error,
180+
v8::Local<v8::Message> message);
181+
178182
private:
179183
using MessageQueue = std::vector<std::pair<int, String16>>;
180184
enum class State { kNew, kAccepting, kConnected, kDone, kError };
@@ -334,6 +338,10 @@ class V8NodeInspector : public blink::V8InspectorClient {
334338
session_->dispatchProtocolMessage(message);
335339
}
336340

341+
blink::V8Inspector* inspector() {
342+
return inspector_.get();
343+
}
344+
337345
private:
338346
AgentImpl* agent_;
339347
v8::Isolate* isolate_;
@@ -495,6 +503,46 @@ void AgentImpl::InstallInspectorOnProcess() {
495503
env->SetMethod(inspector, "wrapConsoleCall", InspectorWrapConsoleCall);
496504
}
497505

506+
String16 ToProtocolString(v8::Local<v8::Value> value) {
507+
if (value.IsEmpty() || value->IsNull() || value->IsUndefined() ||
508+
!value->IsString()) {
509+
return String16();
510+
}
511+
v8::Local<v8::String> string_value = v8::Local<v8::String>::Cast(value);
512+
wstring buffer(string_value->Length(), '\0');
513+
string_value->Write(&buffer[0], 0, string_value->Length());
514+
return String16(buffer);
515+
}
516+
517+
void AgentImpl::FatalException(v8::Local<v8::Value> error,
518+
v8::Local<v8::Message> message) {
519+
if (!IsStarted())
520+
return;
521+
auto env = parent_env_;
522+
v8::Local<v8::Context> context = env->context();
523+
524+
int script_id = message->GetScriptOrigin().ScriptID()->Value();
525+
std::unique_ptr<blink::V8StackTrace> stack_trace =
526+
inspector_->inspector()->createStackTrace(message->GetStackTrace());
527+
528+
if (stack_trace && !stack_trace->isEmpty() &&
529+
String16::fromInteger(script_id) == stack_trace->topScriptId()) {
530+
script_id = 0;
531+
}
532+
533+
inspector_->inspector()->exceptionThrown(
534+
context,
535+
"Uncaught",
536+
error,
537+
ToProtocolString(message->Get()),
538+
ToProtocolString(message->GetScriptResourceName()),
539+
message->GetLineNumber(context).FromMaybe(0),
540+
message->GetStartColumn(context).FromMaybe(0),
541+
std::move(stack_trace),
542+
script_id);
543+
WaitForDisconnect();
544+
}
545+
498546
// static
499547
void AgentImpl::ThreadCbIO(void* agent) {
500548
static_cast<AgentImpl*>(agent)->WorkerRunIO();
@@ -714,5 +762,11 @@ void Agent::WaitForDisconnect() {
714762
impl->WaitForDisconnect();
715763
}
716764

765+
void Agent::FatalException(v8::Local<v8::Value> error,
766+
v8::Local<v8::Message> message) {
767+
impl->FatalException(error, message);
768+
}
769+
770+
717771
} // namespace inspector
718772
} // namespace node

src/inspector_agent.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ class Environment;
1212

1313
namespace v8 {
1414
class Platform;
15+
template<typename T>
16+
class Local;
17+
class Value;
18+
class Message;
1519
} // namespace v8
1620

1721
namespace node {
@@ -32,6 +36,9 @@ class Agent {
3236
bool IsStarted();
3337
bool IsConnected();
3438
void WaitForDisconnect();
39+
40+
void FatalException(v8::Local<v8::Value> error,
41+
v8::Local<v8::Message> message);
3542
private:
3643
AgentImpl* impl;
3744
};

src/node.cc

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2520,31 +2520,43 @@ void FatalException(Isolate* isolate,
25202520
Local<Function> fatal_exception_function =
25212521
process_object->Get(fatal_exception_string).As<Function>();
25222522

2523+
int exit_code = 0;
25232524
if (!fatal_exception_function->IsFunction()) {
25242525
// failed before the process._fatalException function was added!
25252526
// this is probably pretty bad. Nothing to do but report and exit.
25262527
ReportException(env, error, message);
2527-
exit(6);
2528+
exit_code = 6;
25282529
}
25292530

2530-
TryCatch fatal_try_catch(isolate);
2531+
if (exit_code == 0) {
2532+
TryCatch fatal_try_catch(isolate);
25312533

2532-
// Do not call FatalException when _fatalException handler throws
2533-
fatal_try_catch.SetVerbose(false);
2534+
// Do not call FatalException when _fatalException handler throws
2535+
fatal_try_catch.SetVerbose(false);
25342536

2535-
// this will return true if the JS layer handled it, false otherwise
2536-
Local<Value> caught =
2537-
fatal_exception_function->Call(process_object, 1, &error);
2537+
// this will return true if the JS layer handled it, false otherwise
2538+
Local<Value> caught =
2539+
fatal_exception_function->Call(process_object, 1, &error);
25382540

2539-
if (fatal_try_catch.HasCaught()) {
2540-
// the fatal exception function threw, so we must exit
2541-
ReportException(env, fatal_try_catch);
2542-
exit(7);
2541+
if (fatal_try_catch.HasCaught()) {
2542+
// the fatal exception function threw, so we must exit
2543+
ReportException(env, fatal_try_catch);
2544+
exit_code = 7;
2545+
}
2546+
2547+
if (exit_code == 0 && false == caught->BooleanValue()) {
2548+
ReportException(env, error, message);
2549+
exit_code = 1;
2550+
}
25432551
}
25442552

2545-
if (false == caught->BooleanValue()) {
2546-
ReportException(env, error, message);
2547-
exit(1);
2553+
if (exit_code) {
2554+
#if HAVE_INSPECTOR
2555+
if (use_inspector) {
2556+
env->inspector_agent()->FatalException(error, message);
2557+
}
2558+
#endif
2559+
exit(exit_code);
25482560
}
25492561
}
25502562

0 commit comments

Comments
 (0)