Skip to content

Commit 26cd48f

Browse files
alexkozyofrobots
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 cb2e83e commit 26cd48f

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
@@ -2464,31 +2464,43 @@ void FatalException(Isolate* isolate,
24642464
Local<Function> fatal_exception_function =
24652465
process_object->Get(fatal_exception_string).As<Function>();
24662466

2467+
int exit_code = 0;
24672468
if (!fatal_exception_function->IsFunction()) {
24682469
// failed before the process._fatalException function was added!
24692470
// this is probably pretty bad. Nothing to do but report and exit.
24702471
ReportException(env, error, message);
2471-
exit(6);
2472+
exit_code = 6;
24722473
}
24732474

2474-
TryCatch fatal_try_catch(isolate);
2475+
if (exit_code == 0) {
2476+
TryCatch fatal_try_catch(isolate);
24752477

2476-
// Do not call FatalException when _fatalException handler throws
2477-
fatal_try_catch.SetVerbose(false);
2478+
// Do not call FatalException when _fatalException handler throws
2479+
fatal_try_catch.SetVerbose(false);
24782480

2479-
// this will return true if the JS layer handled it, false otherwise
2480-
Local<Value> caught =
2481-
fatal_exception_function->Call(process_object, 1, &error);
2481+
// this will return true if the JS layer handled it, false otherwise
2482+
Local<Value> caught =
2483+
fatal_exception_function->Call(process_object, 1, &error);
24822484

2483-
if (fatal_try_catch.HasCaught()) {
2484-
// the fatal exception function threw, so we must exit
2485-
ReportException(env, fatal_try_catch);
2486-
exit(7);
2485+
if (fatal_try_catch.HasCaught()) {
2486+
// the fatal exception function threw, so we must exit
2487+
ReportException(env, fatal_try_catch);
2488+
exit_code = 7;
2489+
}
2490+
2491+
if (exit_code == 0 && false == caught->BooleanValue()) {
2492+
ReportException(env, error, message);
2493+
exit_code = 1;
2494+
}
24872495
}
24882496

2489-
if (false == caught->BooleanValue()) {
2490-
ReportException(env, error, message);
2491-
exit(1);
2497+
if (exit_code) {
2498+
#if HAVE_INSPECTOR
2499+
if (use_inspector) {
2500+
env->inspector_agent()->FatalException(error, message);
2501+
}
2502+
#endif
2503+
exit(exit_code);
24922504
}
24932505
}
24942506

0 commit comments

Comments
 (0)