summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/inspector_agent.cc54
-rw-r--r--src/inspector_agent.h7
-rw-r--r--src/node.cc40
3 files changed, 87 insertions, 14 deletions
diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc
index 78fc3719a6..5b6a8f01bb 100644
--- a/src/inspector_agent.cc
+++ b/src/inspector_agent.cc
@@ -13,6 +13,7 @@
#include "platform/v8_inspector/public/V8Inspector.h"
#include "platform/v8_inspector/public/V8InspectorClient.h"
#include "platform/v8_inspector/public/V8InspectorSession.h"
+#include "platform/v8_inspector/public/V8StackTrace.h"
#include "platform/inspector_protocol/FrontendChannel.h"
#include "platform/inspector_protocol/String16.h"
#include "platform/inspector_protocol/Values.h"
@@ -175,6 +176,9 @@ class AgentImpl {
bool IsConnected() { return state_ == State::kConnected; }
void WaitForDisconnect();
+ void FatalException(v8::Local<v8::Value> error,
+ v8::Local<v8::Message> message);
+
private:
using MessageQueue = std::vector<std::pair<int, String16>>;
enum class State { kNew, kAccepting, kConnected, kDone, kError };
@@ -334,6 +338,10 @@ class V8NodeInspector : public blink::V8InspectorClient {
session_->dispatchProtocolMessage(message);
}
+ blink::V8Inspector* inspector() {
+ return inspector_.get();
+ }
+
private:
AgentImpl* agent_;
v8::Isolate* isolate_;
@@ -495,6 +503,46 @@ void AgentImpl::InstallInspectorOnProcess() {
env->SetMethod(inspector, "wrapConsoleCall", InspectorWrapConsoleCall);
}
+String16 ToProtocolString(v8::Local<v8::Value> value) {
+ if (value.IsEmpty() || value->IsNull() || value->IsUndefined() ||
+ !value->IsString()) {
+ return String16();
+ }
+ v8::Local<v8::String> string_value = v8::Local<v8::String>::Cast(value);
+ wstring buffer(string_value->Length(), '\0');
+ string_value->Write(&buffer[0], 0, string_value->Length());
+ return String16(buffer);
+}
+
+void AgentImpl::FatalException(v8::Local<v8::Value> error,
+ v8::Local<v8::Message> message) {
+ if (!IsStarted())
+ return;
+ auto env = parent_env_;
+ v8::Local<v8::Context> context = env->context();
+
+ int script_id = message->GetScriptOrigin().ScriptID()->Value();
+ std::unique_ptr<blink::V8StackTrace> stack_trace =
+ inspector_->inspector()->createStackTrace(message->GetStackTrace());
+
+ if (stack_trace && !stack_trace->isEmpty() &&
+ String16::fromInteger(script_id) == stack_trace->topScriptId()) {
+ script_id = 0;
+ }
+
+ inspector_->inspector()->exceptionThrown(
+ context,
+ "Uncaught",
+ error,
+ ToProtocolString(message->Get()),
+ ToProtocolString(message->GetScriptResourceName()),
+ message->GetLineNumber(context).FromMaybe(0),
+ message->GetStartColumn(context).FromMaybe(0),
+ std::move(stack_trace),
+ script_id);
+ WaitForDisconnect();
+}
+
// static
void AgentImpl::ThreadCbIO(void* agent) {
static_cast<AgentImpl*>(agent)->WorkerRunIO();
@@ -714,5 +762,11 @@ void Agent::WaitForDisconnect() {
impl->WaitForDisconnect();
}
+void Agent::FatalException(v8::Local<v8::Value> error,
+ v8::Local<v8::Message> message) {
+ impl->FatalException(error, message);
+}
+
+
} // namespace inspector
} // namespace node
diff --git a/src/inspector_agent.h b/src/inspector_agent.h
index f2b2c1a187..43433fdc6e 100644
--- a/src/inspector_agent.h
+++ b/src/inspector_agent.h
@@ -12,6 +12,10 @@ class Environment;
namespace v8 {
class Platform;
+template<typename T>
+class Local;
+class Value;
+class Message;
} // namespace v8
namespace node {
@@ -32,6 +36,9 @@ class Agent {
bool IsStarted();
bool IsConnected();
void WaitForDisconnect();
+
+ void FatalException(v8::Local<v8::Value> error,
+ v8::Local<v8::Message> message);
private:
AgentImpl* impl;
};
diff --git a/src/node.cc b/src/node.cc
index dbc2478448..3227331934 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -2464,31 +2464,43 @@ void FatalException(Isolate* isolate,
Local<Function> fatal_exception_function =
process_object->Get(fatal_exception_string).As<Function>();
+ int exit_code = 0;
if (!fatal_exception_function->IsFunction()) {
// failed before the process._fatalException function was added!
// this is probably pretty bad. Nothing to do but report and exit.
ReportException(env, error, message);
- exit(6);
+ exit_code = 6;
}
- TryCatch fatal_try_catch(isolate);
+ if (exit_code == 0) {
+ TryCatch fatal_try_catch(isolate);
- // Do not call FatalException when _fatalException handler throws
- fatal_try_catch.SetVerbose(false);
+ // Do not call FatalException when _fatalException handler throws
+ fatal_try_catch.SetVerbose(false);
- // this will return true if the JS layer handled it, false otherwise
- Local<Value> caught =
- fatal_exception_function->Call(process_object, 1, &error);
+ // this will return true if the JS layer handled it, false otherwise
+ Local<Value> caught =
+ fatal_exception_function->Call(process_object, 1, &error);
- if (fatal_try_catch.HasCaught()) {
- // the fatal exception function threw, so we must exit
- ReportException(env, fatal_try_catch);
- exit(7);
+ if (fatal_try_catch.HasCaught()) {
+ // the fatal exception function threw, so we must exit
+ ReportException(env, fatal_try_catch);
+ exit_code = 7;
+ }
+
+ if (exit_code == 0 && false == caught->BooleanValue()) {
+ ReportException(env, error, message);
+ exit_code = 1;
+ }
}
- if (false == caught->BooleanValue()) {
- ReportException(env, error, message);
- exit(1);
+ if (exit_code) {
+#if HAVE_INSPECTOR
+ if (use_inspector) {
+ env->inspector_agent()->FatalException(error, message);
+ }
+#endif
+ exit(exit_code);
}
}