Skip to content
This repository was archived by the owner on Jun 18, 2021. It is now read-only.

Commit 0645644

Browse files
committed
Fix version reporting in NodeReport section
Report the versions of Node.js and its components based on the runtime and not compile time constants. Extend the tests to validate the versions reported in the report. Fixes: #29
1 parent 95a046e commit 0645644

File tree

4 files changed

+101
-14
lines changed

4 files changed

+101
-14
lines changed

src/module.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ void Initialize(v8::Local<v8::Object> exports) {
302302
node_isolate = isolate;
303303

304304
SetLoadTime();
305+
SetVersionString(isolate);
305306

306307
const char* verbose_switch = secure_getenv("NODEREPORT_VERBOSE");
307308
if (verbose_switch != nullptr) {

src/node_report.cc

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
#include "node_report.h"
2-
#include "node_version.h"
32
#include "v8.h"
43
#include "time.h"
5-
#include "zlib.h"
6-
#include "ares.h"
74

85
#include <fcntl.h>
96
#include <string.h>
@@ -52,7 +49,7 @@ using v8::String;
5249
using v8::V8;
5350

5451
// Internal/static function declarations
55-
static void PrintVersionInformation(FILE* fp);
52+
static void PrintVersionInformation(FILE* fp, Isolate* isolate);
5653
static void PrintJavaScriptStack(FILE* fp, Isolate* isolate, DumpEvent event, const char* location);
5754
static void PrintStackFromStackTrace(FILE* fp, Isolate* isolate, DumpEvent event);
5855
static void PrintStackFrame(FILE* fp, Isolate* isolate, Local<StackFrame> frame, int index, void* pc);
@@ -70,6 +67,7 @@ const char* v8_states[] = {"JS", "GC", "COMPILER", "OTHER", "EXTERNAL", "IDLE"};
7067
static bool report_active = false; // recursion protection
7168
static char report_filename[NR_MAXNAME + 1] = "";
7269
static char report_directory[NR_MAXPATH + 1] = ""; // defaults to current working directory
70+
static std::string versionString = "Unable to determine Node.js version\n";
7371
#ifdef _WIN32
7472
static SYSTEMTIME loadtime_tm_struct; // module load time
7573
#else // UNIX, OSX
@@ -189,6 +187,73 @@ unsigned int ProcessNodeReportVerboseSwitch(const char* args) {
189187
return 0; // Default is verbose mode off
190188
}
191189

190+
void SetVersionString(Isolate* isolate) {
191+
Nan::MaybeLocal<String> processProp = Nan::New<String>("process");
192+
if (processProp.IsEmpty()) {
193+
return;
194+
}
195+
Nan::MaybeLocal<Value> process = Nan::Get(
196+
isolate->GetCurrentContext()->Global(),
197+
processProp.ToLocalChecked());
198+
if (process.IsEmpty() || process.ToLocalChecked()->IsUndefined()) {
199+
return;
200+
}
201+
Nan::MaybeLocal<String> versionProp = Nan::New<String>("version");
202+
if (versionProp.IsEmpty()) {
203+
return;
204+
}
205+
Nan::MaybeLocal<Value> version = Nan::Get(
206+
process.ToLocalChecked().As<Object>(),
207+
versionProp.ToLocalChecked());
208+
if (version.IsEmpty() || version.ToLocalChecked()->IsUndefined()) {
209+
return;
210+
}
211+
Nan::Utf8String nodeVersion(version.ToLocalChecked());
212+
versionString.assign("Node.js version: ");
213+
versionString.append(*nodeVersion);
214+
versionString.append("\n");
215+
216+
// Get the component versions
217+
Nan::MaybeLocal<String> versionsProp = Nan::New<String>("versions");
218+
if (versionsProp.IsEmpty()) {
219+
return;
220+
}
221+
Nan::MaybeLocal<Value> versions = Nan::Get(
222+
process.ToLocalChecked().As<Object>(),
223+
versionsProp.ToLocalChecked());
224+
if (versions.IsEmpty() || versions.ToLocalChecked()->IsUndefined()) {
225+
return;
226+
}
227+
Local<Object> versionsObj = versions.ToLocalChecked().As<Object>();
228+
Nan::MaybeLocal<v8::Array> keys = Nan::GetOwnPropertyNames(versionsObj);
229+
if (keys.IsEmpty() || keys.ToLocalChecked()->IsUndefined()) {
230+
return;
231+
}
232+
Local<v8::Array> components = keys.ToLocalChecked();
233+
for (uint32_t i = 0, nComps = (*components)->Length(); i < nComps; i++) {
234+
Nan::MaybeLocal<Value> maybeComp = Nan::Get(components.As<Object>(), i);
235+
if (maybeComp.IsEmpty()) {
236+
continue;
237+
}
238+
Local<Value> compValue = maybeComp.ToLocalChecked();
239+
Nan::MaybeLocal<Value> maybeVers = Nan::Get(versionsObj, compValue);
240+
if (maybeVers.IsEmpty()) {
241+
continue;
242+
}
243+
Local<Value> versValue = maybeVers.ToLocalChecked();
244+
Nan::Utf8String compName(compValue);
245+
Nan::Utf8String compVersion(versValue);
246+
// Don't duplicate the Node.js version
247+
if (!strcmp("node", *compName)) {
248+
continue;
249+
}
250+
versionString.append(*compName);
251+
versionString.append(": ");
252+
versionString.append(*compVersion);
253+
versionString.append("\n");
254+
}
255+
}
256+
192257
/*******************************************************************************
193258
* Function to save the nodereport module load time value
194259
*******************************************************************************/
@@ -317,7 +382,7 @@ void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, c
317382
fflush(fp);
318383

319384
// Print Node.js and OS version information
320-
PrintVersionInformation(fp);
385+
PrintVersionInformation(fp, isolate);
321386
fflush(fp);
322387

323388
// Print summary JavaScript stack backtrace
@@ -369,12 +434,10 @@ void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, c
369434
* Function to print Node.js version, OS version and machine information
370435
*
371436
******************************************************************************/
372-
static void PrintVersionInformation(FILE* fp) {
437+
static void PrintVersionInformation(FILE* fp, Isolate* isolate) {
373438

374439
// Print Node.js and deps component versions
375-
fprintf(fp, "\nNode.js version: %s\n", NODE_VERSION);
376-
fprintf(fp, "(v8: %s, libuv: %s, zlib: %s, ares: %s)\n",
377-
V8::GetVersion(), uv_version_string(), ZLIB_VERSION, ARES_VERSION_STR);
440+
fprintf(fp, "\n%s", versionString.c_str());
378441

379442
// Print operating system and machine information (Windows)
380443
#ifdef _WIN32

src/node_report.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ void ProcessNodeReportDirectory(const char* args);
4343
unsigned int ProcessNodeReportVerboseSwitch(const char* args);
4444

4545
void SetLoadTime();
46+
void SetVersionString(Isolate* isolate);
4647

4748
// Local implementation of secure_getenv()
4849
inline const char* secure_getenv(const char* key) {

test/common.js

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ const REPORT_SECTIONS = [
99
'System Information'
1010
];
1111

12+
const reNewline = '(?:\\r*\\n)';
13+
1214
exports.findReports = (pid) => {
1315
// Default filenames are of the form NodeReport.<date>.<time>.<pid>.<seq>.txt
1416
const format = '^NodeReport\\.\\d+\\.\\d+\\.' + pid + '\\.\\d+\\.txt$';
@@ -29,16 +31,36 @@ exports.validate = (t, report, pid) => {
2931
t.test('Validating ' + report, (t) => {
3032
fs.readFile(report, (err, data) => {
3133
const reportContents = data.toString();
32-
const plan = REPORT_SECTIONS.length + (pid ? 1 : 0);
34+
const nodeComponents = Object.keys(process.versions);
35+
const plan = REPORT_SECTIONS.length + (pid ? 1 : 0)
36+
+ nodeComponents.length;
3337
t.plan(plan);
34-
if (pid) {
35-
t.match(reportContents, new RegExp('Process ID: ' + pid),
36-
'Checking report contains expected process ID ' + pid);
37-
}
3838
REPORT_SECTIONS.forEach((section) => {
3939
t.match(reportContents, new RegExp('==== ' + section),
4040
'Checking report contains ' + section + ' section');
4141
});
42+
const nodeReportSection = getSection(reportContents, 'NodeReport');
43+
if (pid) {
44+
t.match(nodeReportSection, new RegExp('Process ID: ' + pid),
45+
'NodeReport section contains expected process ID');
46+
}
47+
t.match(nodeReportSection,
48+
new RegExp('Node.js version: ' + process.version),
49+
'NodeReport section contains expected Node.js version');
50+
nodeComponents.forEach((c) => {
51+
if (c !== 'node') {
52+
t.match(nodeReportSection,
53+
new RegExp(c + ': ' + process.versions[c]),
54+
'NodeReport section contains expected ' + c + ' version');
55+
}
56+
});
4257
});
4358
});
4459
};
60+
61+
const getSection = (report, section) => {
62+
const re = new RegExp('==== ' + section + ' =+' + reNewline + '+([\\S\\s]+?)'
63+
+ reNewline + '+={80}' + reNewline);
64+
const match = re.exec(report);
65+
return match ? match[1] : '';
66+
};

0 commit comments

Comments
 (0)