From 15fd45af9aed0ee463bfbd8de98e0b9baa925518 Mon Sep 17 00:00:00 2001 From: Howard Hellyer Date: Wed, 29 Mar 2017 10:15:30 +0100 Subject: [PATCH 1/6] Allow Error object to be passed to node-report Add an optional parameter to triggerReport and getReport so an Error object can be passed. If it is passed the error message and stack trace it contains will be added to the node-report output in a new "JavaScript Exception Details" section. This makes node-report more useful in custom error handlers as it will include the stack trace of the original error as well as the stack trace where the error was handled. --- src/module.cc | 26 ++++++++++++++++++++------ src/node_report.cc | 46 ++++++++++++++++++++++++++++++++++++---------- src/node_report.h | 4 ++-- 3 files changed, 58 insertions(+), 18 deletions(-) diff --git a/src/module.cc b/src/module.cc index fb60a2b..1e2b30a 100644 --- a/src/module.cc +++ b/src/module.cc @@ -51,6 +51,8 @@ NAN_METHOD(TriggerReport) { Nan::HandleScope scope; v8::Isolate* isolate = info.GetIsolate(); char filename[NR_MAXNAME + 1] = ""; + v8::MaybeLocal error; + int err_index = 0; if (info[0]->IsString()) { // Filename parameter supplied @@ -60,9 +62,16 @@ NAN_METHOD(TriggerReport) { } else { Nan::ThrowError("node-report: filename parameter is too long"); } + err_index++; } + + // We need to pass the javascript object so we can query if for a stack trace. + if( info[err_index]->IsNativeError()) { + error = info[err_index]; + } + if (nodereport_events & NR_APICALL) { - TriggerNodeReport(isolate, kJavaScript, "JavaScript API", __func__, filename); + TriggerNodeReport(isolate, kJavaScript, "JavaScript API", __func__, filename, error); // Return value is the report filename info.GetReturnValue().Set(Nan::New(filename).ToLocalChecked()); } @@ -77,7 +86,12 @@ NAN_METHOD(GetReport) { v8::Isolate* isolate = info.GetIsolate(); std::ostringstream out; - GetNodeReport(isolate, kJavaScript, "JavaScript API", __func__, out); + v8::MaybeLocal error; + if( info[0]->IsNativeError()) { + error = info[0]; + } + + GetNodeReport(isolate, kJavaScript, "JavaScript API", __func__, error, out); // Return value is the contents of a report as a string. info.GetReturnValue().Set(Nan::New(out.str()).ToLocalChecked()); } @@ -156,7 +170,7 @@ static void OnFatalError(const char* location, const char* message) { } // Trigger report if requested if (nodereport_events & NR_FATALERROR) { - TriggerNodeReport(Isolate::GetCurrent(), kFatalError, message, location, nullptr); + TriggerNodeReport(Isolate::GetCurrent(), kFatalError, message, location, nullptr, v8::MaybeLocal()); } fflush(stderr); raise(SIGABRT); @@ -165,7 +179,7 @@ static void OnFatalError(const char* location, const char* message) { bool OnUncaughtException(v8::Isolate* isolate) { // Trigger report if requested if (nodereport_events & NR_EXCEPTION) { - TriggerNodeReport(isolate, kException, "exception", __func__, nullptr); + TriggerNodeReport(isolate, kException, "exception", __func__, nullptr, v8::MaybeLocal()); } if ((commandline_string.find("abort-on-uncaught-exception") != std::string::npos) || (commandline_string.find("abort_on_uncaught_exception") != std::string::npos)) { @@ -231,7 +245,7 @@ static void SignalDumpInterruptCallback(Isolate* isolate, void* data) { fprintf(stdout, "node-report: SignalDumpInterruptCallback triggering report\n"); } TriggerNodeReport(isolate, kSignal_JS, - node::signo_string(report_signal), __func__, nullptr); + node::signo_string(report_signal), __func__, nullptr, v8::MaybeLocal()); } report_signal = 0; } @@ -246,7 +260,7 @@ static void SignalDumpAsyncCallback(uv_async_t* handle) { fprintf(stdout, "node-report: SignalDumpAsyncCallback triggering NodeReport\n"); } TriggerNodeReport(Isolate::GetCurrent(), kSignal_UV, - node::signo_string(report_signal), __func__, nullptr); + node::signo_string(report_signal), __func__, nullptr, v8::MaybeLocal()); } report_signal = 0; } diff --git a/src/node_report.cc b/src/node_report.cc index cb4827b..d5eadb4 100644 --- a/src/node_report.cc +++ b/src/node_report.cc @@ -82,10 +82,11 @@ typedef struct tm TIME_TYPE; #endif // Internal/static function declarations -static void WriteNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* filename, std::ostream &out, TIME_TYPE* time); +static void WriteNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* filename, std::ostream &out, v8::MaybeLocal error, TIME_TYPE* time); static void PrintCommandLine(std::ostream& out); static void PrintVersionInformation(std::ostream& out); static void PrintJavaScriptStack(std::ostream& out, Isolate* isolate, DumpEvent event, const char* location); +static void PrintJavaScriptErrorStack(std::ostream& out, Isolate* isolate, v8::MaybeLocal error); static void PrintStackFromStackTrace(std::ostream& out, Isolate* isolate, DumpEvent event); static void PrintStackFrame(std::ostream& out, Isolate* isolate, Local frame, int index, void* pc); static void PrintNativeStack(std::ostream& out); @@ -379,7 +380,7 @@ void SetCommandLine() { * const char* location * char* name - in/out - returns the report filename ******************************************************************************/ -void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* name) { +void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* name, v8::MaybeLocal error) { // Recursion check for report in progress, bail out if (report_active) return; report_active = true; @@ -460,7 +461,7 @@ void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, c // Pass our stream about by reference, not by copying it. std::ostream &out = outfile.is_open() ? outfile : *outstream; - WriteNodeReport(isolate, event, message, location, filename, out, &tm_struct); + WriteNodeReport(isolate, event, message, location, filename, out, error, &tm_struct); // Do not close stdout/stderr, only close files we opened. if(outfile.is_open()) { @@ -474,7 +475,7 @@ void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, c } -void GetNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, std::ostream& out) { +void GetNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, v8::MaybeLocal error, std::ostream& out) { // Obtain the current time and the pid (platform dependent) TIME_TYPE tm_struct; #ifdef _WIN32 @@ -484,7 +485,7 @@ void GetNodeReport(Isolate* isolate, DumpEvent event, const char* message, const gettimeofday(&time_val, nullptr); localtime_r(&time_val.tv_sec, &tm_struct); #endif - WriteNodeReport(isolate, event, message, location, nullptr, out, &tm_struct); + WriteNodeReport(isolate, event, message, location, nullptr, out, error, &tm_struct); } static void walkHandle(uv_handle_t* h, void* arg) { @@ -531,7 +532,7 @@ static void walkHandle(uv_handle_t* h, void* arg) { *out << buf; } -static void WriteNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* filename, std::ostream &out, TIME_TYPE* tm_struct) { +static void WriteNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* filename, std::ostream &out, v8::MaybeLocal error, TIME_TYPE* tm_struct) { #ifdef _WIN32 DWORD pid = GetCurrentProcessId(); @@ -589,6 +590,11 @@ static void WriteNodeReport(Isolate* isolate, DumpEvent event, const char* messa PrintNativeStack(out); out << std::flush; + // Print the stack trace and message from the Error object. + // (If one was provided.) + PrintJavaScriptErrorStack(out, isolate, error); + out << std::flush; + // Print V8 Heap and Garbage Collector information PrintGCStatistics(out, isolate); out << std::flush; @@ -791,6 +797,25 @@ static void PrintJavaScriptStack(std::ostream& out, Isolate* isolate, DumpEvent #endif } +static void PrintJavaScriptErrorStack(std::ostream& out, Isolate* isolate, v8::MaybeLocal error) { + if (error.IsEmpty() || !error.ToLocalChecked()->IsNativeError()) { + return; + } + + out << "\n================================================================================"; + out << "\n==== JavaScript Exception Details ==============================================\n\n"; + Local message = v8::Exception::CreateMessage(isolate, error.ToLocalChecked()); + Nan::Utf8String message_str(message->Get()); + + out << *message_str << "\n"; + + Local stack = v8::Exception::GetStackTrace(error.ToLocalChecked()); + // Print the stack trace, adding in the pc values from GetStackSample() if available + for (int i = 0; i < stack->GetFrameCount(); i++) { + PrintStackFrame(out, isolate, stack->GetFrame(i), i, nullptr); + } +} + /******************************************************************************* * Function to print stack using GetStackSample() and StackTrace::StackTrace() * @@ -842,13 +867,14 @@ static void PrintStackFrame(std::ostream& out, Isolate* isolate, LocalIsEval()) { diff --git a/src/node_report.h b/src/node_report.h index 567daa5..3915ccf 100644 --- a/src/node_report.h +++ b/src/node_report.h @@ -32,8 +32,8 @@ using v8::StackFrame; enum DumpEvent {kException, kFatalError, kSignal_JS, kSignal_UV, kJavaScript}; -void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* name); -void GetNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, std::ostream& out); +void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* name, v8::MaybeLocal error); +void GetNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, v8::MaybeLocal error, std::ostream& out); unsigned int ProcessNodeReportEvents(const char* args); unsigned int ProcessNodeReportSignal(const char* args); From c73968a8d58b508a5ca099049bf65d3245127870 Mon Sep 17 00:00:00 2001 From: Howard Hellyer Date: Fri, 21 Apr 2017 14:05:06 +0100 Subject: [PATCH 2/6] Add a test case for passing an Error object to triggerReport Update the API docs for getReport and triggerReport. Fix crash when error object does not include a stack trace. --- README.md | 12 ++++++++++++ src/node_report.cc | 4 ++++ test/common.js | 13 ++++++++++++- test/test-api-pass-error.js | 29 +++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 test/test-api-pass-error.js diff --git a/README.md b/README.md index 378aa24..78ce5fb 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,18 @@ can be specified as a parameter on the `triggerReport()` call. nodereport.triggerReport("myReportName"); ``` +Both triggerReport() and getReport() can take an optional Error object as a parameter. If an Error object is provided the message and stack trace from the object will be included in the report in the `JavaScript Exception Details` section. When using node-report to handle errors in a callback or an exception handler this allows the report to include the location of the original error as well as where it was handled. +If both a filename and Error object are passed to triggerReport() the Error object should be the second parameter. + +```js +fs.stat('/usr/local/fake/fake.txt', (err, stats) => { + if(err) { + nodereport.triggerReport(err); + } + ... +}); +``` + ## Configuration Additional configuration is available using the following APIs: diff --git a/src/node_report.cc b/src/node_report.cc index d5eadb4..a8d5918 100644 --- a/src/node_report.cc +++ b/src/node_report.cc @@ -810,6 +810,10 @@ static void PrintJavaScriptErrorStack(std::ostream& out, Isolate* isolate, v8::M out << *message_str << "\n"; Local stack = v8::Exception::GetStackTrace(error.ToLocalChecked()); + if (stack.IsEmpty()) { + out << "\nNo stack trace available from Exception::GetStackTrace()\n"; + return; + } // Print the stack trace, adding in the pc values from GetStackSample() if available for (int i = 0; i < stack->GetFrameCount(); i++) { PrintStackFrame(out, isolate, stack->GetFrame(i), i, nullptr); diff --git a/test/common.js b/test/common.js index 1c0a969..70982b1 100644 --- a/test/common.js +++ b/test/common.js @@ -58,11 +58,18 @@ exports.validateContent = function validateContent(data, t, options) { const expectedVersions = options ? options.expectedVersions || nodeComponents : nodeComponents; - var plan = REPORT_SECTIONS.length + nodeComponents.length + 5; + const expectedException = options.expectedException; + if (options.expectedException) { + REPORT_SECTIONS.push('JavaScript Exception Details'); + } + + let plan = REPORT_SECTIONS.length + nodeComponents.length + 5; if (options.commandline) plan++; + if (options.expectedException) plan++; const glibcRE = /\(glibc:\s([\d.]+)/; const nodeReportSection = getSection(reportContents, 'Node Report'); const sysInfoSection = getSection(reportContents, 'System Information'); + const exceptionSection = getSection(reportContents, 'JavaScript Exception Details'); const libcPath = getLibcPath(sysInfoSection); const libcVersion = getLibcVersion(libcPath); if (glibcRE.test(nodeReportSection) && libcVersion) plan++; @@ -84,6 +91,10 @@ exports.validateContent = function validateContent(data, t, options) { new RegExp('Node.js version: ' + process.version), 'Node Report header section contains expected Node.js version'); } + if( options && options.expectedException) { + t.match(exceptionSection, new RegExp('Uncaught Error: ' + options.expectedException), + 'Node Report JavaScript Exception contains expected message'); + } if (options && options.commandline) { if (this.isWindows()) { // On Windows we need to strip double quotes from the command line in diff --git a/test/test-api-pass-error.js b/test/test-api-pass-error.js new file mode 100644 index 0000000..3857bbb --- /dev/null +++ b/test/test-api-pass-error.js @@ -0,0 +1,29 @@ +'use strict'; + +// Testcase for passing an error object to the API call. + +if (process.argv[2] === 'child') { + const nodereport = require('../'); + try { + throw new Error("Testing error handling"); + } catch (err) { + nodereport.triggerReport(err); + } +} else { + const common = require('./common.js'); + const spawn = require('child_process').spawn; + const tap = require('tap'); + + const child = spawn(process.execPath, [__filename, 'child']); + child.on('exit', (code) => { + tap.plan(3); + tap.equal(code, 0, 'Process exited cleanly'); + const reports = common.findReports(child.pid); + tap.equal(reports.length, 1, 'Found reports ' + reports); + const report = reports[0]; + common.validate(tap, report, {pid: child.pid, + commandline: child.spawnargs.join(' '), + expectedException: "Testing error handling", + }); + }); +} From 5b75c5e20821d7d29feac48e2138990163fc429d Mon Sep 17 00:00:00 2001 From: Howard Hellyer Date: Tue, 25 Apr 2017 09:30:37 +0100 Subject: [PATCH 3/6] Wrap text in README.md at 80 characters. --- README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 78ce5fb..d528685 100644 --- a/README.md +++ b/README.md @@ -69,8 +69,15 @@ can be specified as a parameter on the `triggerReport()` call. nodereport.triggerReport("myReportName"); ``` -Both triggerReport() and getReport() can take an optional Error object as a parameter. If an Error object is provided the message and stack trace from the object will be included in the report in the `JavaScript Exception Details` section. When using node-report to handle errors in a callback or an exception handler this allows the report to include the location of the original error as well as where it was handled. -If both a filename and Error object are passed to triggerReport() the Error object should be the second parameter. +Both `triggerReport()` and `getReport()` can take an optional `Error` object +as a parameter. If an `Error` object is provided the message and stack trace +from the object will be included in the report in the `JavaScript Exception +Details` section. +When using node-report to handle errors in a callback or an exception handler +this allows the report to include the location of the original error as well +as where it was handled. +If both a filename and Error object are passed to `triggerReport()` the +`Error` object should be the second parameter. ```js fs.stat('/usr/local/fake/fake.txt', (err, stats) => { From e5edd5f1b5f7f32b76cff15d2d6d2701723c44ab Mon Sep 17 00:00:00 2001 From: Howard Hellyer Date: Tue, 25 Apr 2017 16:21:19 +0100 Subject: [PATCH 4/6] Fix formatting and style issues from review. --- README.md | 6 +++--- src/module.cc | 4 ++-- src/node_report.cc | 2 +- test/common.js | 2 +- test/test-api-pass-error.js | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d528685..a4ae339 100644 --- a/README.md +++ b/README.md @@ -70,18 +70,18 @@ nodereport.triggerReport("myReportName"); ``` Both `triggerReport()` and `getReport()` can take an optional `Error` object -as a parameter. If an `Error` object is provided the message and stack trace +as a parameter. If an `Error` object is provided, the message and stack trace from the object will be included in the report in the `JavaScript Exception Details` section. When using node-report to handle errors in a callback or an exception handler this allows the report to include the location of the original error as well as where it was handled. -If both a filename and Error object are passed to `triggerReport()` the +If both a filename and `Error` object are passed to `triggerReport()` the `Error` object should be the second parameter. ```js fs.stat('/usr/local/fake/fake.txt', (err, stats) => { - if(err) { + if (err) { nodereport.triggerReport(err); } ... diff --git a/src/module.cc b/src/module.cc index 1e2b30a..e09ae57 100644 --- a/src/module.cc +++ b/src/module.cc @@ -66,7 +66,7 @@ NAN_METHOD(TriggerReport) { } // We need to pass the javascript object so we can query if for a stack trace. - if( info[err_index]->IsNativeError()) { + if (info[err_index]->IsNativeError()) { error = info[err_index]; } @@ -87,7 +87,7 @@ NAN_METHOD(GetReport) { std::ostringstream out; v8::MaybeLocal error; - if( info[0]->IsNativeError()) { + if (info[0]->IsNativeError()) { error = info[0]; } diff --git a/src/node_report.cc b/src/node_report.cc index a8d5918..e971cf6 100644 --- a/src/node_report.cc +++ b/src/node_report.cc @@ -871,7 +871,7 @@ static void PrintStackFrame(std::ostream& out, Isolate* isolate, Local Date: Wed, 3 May 2017 16:15:46 +0100 Subject: [PATCH 5/6] Fix output spacing and example code comments from code review. --- README.md | 9 +++++---- src/node_report.cc | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a4ae339..4e7b3f5 100644 --- a/README.md +++ b/README.md @@ -80,10 +80,11 @@ If both a filename and `Error` object are passed to `triggerReport()` the `Error` object should be the second parameter. ```js -fs.stat('/usr/local/fake/fake.txt', (err, stats) => { - if (err) { - nodereport.triggerReport(err); - } +try { + process.chdir('/foo/foo'); +} catch (err) { + nodereport.triggerReport(err); +} ... }); ``` diff --git a/src/node_report.cc b/src/node_report.cc index e971cf6..0017c1d 100644 --- a/src/node_report.cc +++ b/src/node_report.cc @@ -807,14 +807,14 @@ static void PrintJavaScriptErrorStack(std::ostream& out, Isolate* isolate, v8::M Local message = v8::Exception::CreateMessage(isolate, error.ToLocalChecked()); Nan::Utf8String message_str(message->Get()); - out << *message_str << "\n"; + out << *message_str << "\n\n"; Local stack = v8::Exception::GetStackTrace(error.ToLocalChecked()); if (stack.IsEmpty()) { - out << "\nNo stack trace available from Exception::GetStackTrace()\n"; + out << "No stack trace available from Exception::GetStackTrace()\n"; return; } - // Print the stack trace, adding in the pc values from GetStackSample() if available + // Print the stack trace, samples are not available as the exception isn't from the current stack. for (int i = 0; i < stack->GetFrameCount(); i++) { PrintStackFrame(out, isolate, stack->GetFrame(i), i, nullptr); } From 71308889909ec6f9f9dc721f82f855eab80edaee Mon Sep 17 00:00:00 2001 From: Howard Hellyer Date: Thu, 4 May 2017 14:15:27 +0100 Subject: [PATCH 6/6] Fix code review comments: - Correct spelling in comments - Update documentation comment for TriggerNodeReport - v8::MaybeLocal -> MaybeLocal --- src/module.cc | 14 +++++++------- src/node_report.cc | 13 +++++++------ src/node_report.h | 1 + 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/module.cc b/src/module.cc index e09ae57..5c2f76d 100644 --- a/src/module.cc +++ b/src/module.cc @@ -51,7 +51,7 @@ NAN_METHOD(TriggerReport) { Nan::HandleScope scope; v8::Isolate* isolate = info.GetIsolate(); char filename[NR_MAXNAME + 1] = ""; - v8::MaybeLocal error; + MaybeLocal error; int err_index = 0; if (info[0]->IsString()) { @@ -65,7 +65,7 @@ NAN_METHOD(TriggerReport) { err_index++; } - // We need to pass the javascript object so we can query if for a stack trace. + // We need to pass the JavaScript object so we can query it for a stack trace. if (info[err_index]->IsNativeError()) { error = info[err_index]; } @@ -86,7 +86,7 @@ NAN_METHOD(GetReport) { v8::Isolate* isolate = info.GetIsolate(); std::ostringstream out; - v8::MaybeLocal error; + MaybeLocal error; if (info[0]->IsNativeError()) { error = info[0]; } @@ -170,7 +170,7 @@ static void OnFatalError(const char* location, const char* message) { } // Trigger report if requested if (nodereport_events & NR_FATALERROR) { - TriggerNodeReport(Isolate::GetCurrent(), kFatalError, message, location, nullptr, v8::MaybeLocal()); + TriggerNodeReport(Isolate::GetCurrent(), kFatalError, message, location, nullptr, MaybeLocal()); } fflush(stderr); raise(SIGABRT); @@ -179,7 +179,7 @@ static void OnFatalError(const char* location, const char* message) { bool OnUncaughtException(v8::Isolate* isolate) { // Trigger report if requested if (nodereport_events & NR_EXCEPTION) { - TriggerNodeReport(isolate, kException, "exception", __func__, nullptr, v8::MaybeLocal()); + TriggerNodeReport(isolate, kException, "exception", __func__, nullptr, MaybeLocal()); } if ((commandline_string.find("abort-on-uncaught-exception") != std::string::npos) || (commandline_string.find("abort_on_uncaught_exception") != std::string::npos)) { @@ -245,7 +245,7 @@ static void SignalDumpInterruptCallback(Isolate* isolate, void* data) { fprintf(stdout, "node-report: SignalDumpInterruptCallback triggering report\n"); } TriggerNodeReport(isolate, kSignal_JS, - node::signo_string(report_signal), __func__, nullptr, v8::MaybeLocal()); + node::signo_string(report_signal), __func__, nullptr, MaybeLocal()); } report_signal = 0; } @@ -260,7 +260,7 @@ static void SignalDumpAsyncCallback(uv_async_t* handle) { fprintf(stdout, "node-report: SignalDumpAsyncCallback triggering NodeReport\n"); } TriggerNodeReport(Isolate::GetCurrent(), kSignal_UV, - node::signo_string(report_signal), __func__, nullptr, v8::MaybeLocal()); + node::signo_string(report_signal), __func__, nullptr, MaybeLocal()); } report_signal = 0; } diff --git a/src/node_report.cc b/src/node_report.cc index 0017c1d..f6cc7eb 100644 --- a/src/node_report.cc +++ b/src/node_report.cc @@ -82,11 +82,11 @@ typedef struct tm TIME_TYPE; #endif // Internal/static function declarations -static void WriteNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* filename, std::ostream &out, v8::MaybeLocal error, TIME_TYPE* time); +static void WriteNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* filename, std::ostream &out, MaybeLocal error, TIME_TYPE* time); static void PrintCommandLine(std::ostream& out); static void PrintVersionInformation(std::ostream& out); static void PrintJavaScriptStack(std::ostream& out, Isolate* isolate, DumpEvent event, const char* location); -static void PrintJavaScriptErrorStack(std::ostream& out, Isolate* isolate, v8::MaybeLocal error); +static void PrintJavaScriptErrorStack(std::ostream& out, Isolate* isolate, MaybeLocal error); static void PrintStackFromStackTrace(std::ostream& out, Isolate* isolate, DumpEvent event); static void PrintStackFrame(std::ostream& out, Isolate* isolate, Local frame, int index, void* pc); static void PrintNativeStack(std::ostream& out); @@ -379,8 +379,9 @@ void SetCommandLine() { * const char* message * const char* location * char* name - in/out - returns the report filename + * MaybeLocal error - JavaScript Error object. ******************************************************************************/ -void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* name, v8::MaybeLocal error) { +void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* name, MaybeLocal error) { // Recursion check for report in progress, bail out if (report_active) return; report_active = true; @@ -475,7 +476,7 @@ void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, c } -void GetNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, v8::MaybeLocal error, std::ostream& out) { +void GetNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, MaybeLocal error, std::ostream& out) { // Obtain the current time and the pid (platform dependent) TIME_TYPE tm_struct; #ifdef _WIN32 @@ -532,7 +533,7 @@ static void walkHandle(uv_handle_t* h, void* arg) { *out << buf; } -static void WriteNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* filename, std::ostream &out, v8::MaybeLocal error, TIME_TYPE* tm_struct) { +static void WriteNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* filename, std::ostream &out, MaybeLocal error, TIME_TYPE* tm_struct) { #ifdef _WIN32 DWORD pid = GetCurrentProcessId(); @@ -797,7 +798,7 @@ static void PrintJavaScriptStack(std::ostream& out, Isolate* isolate, DumpEvent #endif } -static void PrintJavaScriptErrorStack(std::ostream& out, Isolate* isolate, v8::MaybeLocal error) { +static void PrintJavaScriptErrorStack(std::ostream& out, Isolate* isolate, MaybeLocal error) { if (error.IsEmpty() || !error.ToLocalChecked()->IsNativeError()) { return; } diff --git a/src/node_report.h b/src/node_report.h index 3915ccf..b597303 100644 --- a/src/node_report.h +++ b/src/node_report.h @@ -19,6 +19,7 @@ using v8::String; using v8::Value; using v8::StackTrace; using v8::StackFrame; +using v8::MaybeLocal; // Bit-flags for node-report trigger options #define NR_EXCEPTION 0x01