Comparing version 2.0.0 to 2.0.1
@@ -0,1 +1,4 @@ | ||
# 2.0.1 - 5/16/2017 | ||
- Fix memory explosion when parsing stack for large files [See #320] | ||
# 2.0.0 - 5/10/2017 | ||
@@ -2,0 +5,0 @@ - Properly surface errors to preserve process exit conditions [See #308, #257] |
@@ -144,41 +144,43 @@ 'use strict'; | ||
function parseLines(lines, frame) { | ||
frame.pre_context = lines.slice(Math.max(0, frame.lineno - (LINES_OF_CONTEXT + 1)), frame.lineno - 1); | ||
frame.context_line = lines[frame.lineno - 1]; | ||
frame.post_context = lines.slice(frame.lineno, frame.lineno + LINES_OF_CONTEXT); | ||
function readSourceFiles(filenames, cb) { | ||
// we're relying on filenames being de-duped already | ||
if (filenames.length === 0) return setTimeout(cb, 0, {}); | ||
var sourceFiles = {}; | ||
var numFilesToRead = filenames.length; | ||
return filenames.forEach(function (filename) { | ||
fs.readFile(filename, function (readErr, file) { | ||
if (!readErr) sourceFiles[filename] = file.toString().split('\n'); | ||
if (--numFilesToRead === 0) cb(sourceFiles); | ||
}); | ||
}); | ||
} | ||
function parseStack(err, cb) { | ||
var frames = [], | ||
cache = {}; | ||
if (!err) return cb([]); | ||
if (!err) { | ||
return cb(frames); | ||
} | ||
var stack = stacktrace.parse(err); | ||
// check to make sure that the stack is what we need it to be. | ||
if (!stack || !Array.isArray(stack) || !stack.length || !stack[0].getFileName) { | ||
// lol, stack is fucked | ||
return cb(frames); | ||
// the stack is not the useful thing we were expecting :/ | ||
return cb([]); | ||
} | ||
var callbacks = stack.length; | ||
// Sentry requires the stack trace to be from oldest to newest | ||
// Sentry expects the stack trace to be oldest -> newest, v8 provides newest -> oldest | ||
stack.reverse(); | ||
return stack.forEach(function (line, index) { | ||
var frames = []; | ||
var filesToRead = {}; | ||
stack.forEach(function (line) { | ||
var frame = { | ||
filename: line.getFileName() || '', | ||
lineno: line.getLineNumber(), | ||
colno: line.getColumnNumber(), | ||
'function': getFunction(line), | ||
}, | ||
isInternal = line.isNative() || | ||
frame.filename[0] !== '/' && | ||
frame.filename[0] !== '.' && | ||
frame.filename.indexOf(':\\') !== 1; | ||
filename: line.getFileName() || '', | ||
lineno: line.getLineNumber(), | ||
colno: line.getColumnNumber(), | ||
'function': getFunction(line), | ||
}; | ||
var isInternal = line.isNative() || | ||
frame.filename[0] !== '/' && | ||
frame.filename[0] !== '.' && | ||
frame.filename.indexOf(':\\') !== 1; | ||
// in_app is all that's not an internal Node function or a module within node_modules | ||
@@ -190,26 +192,26 @@ // note that isNative appears to return true even for node core libraries | ||
// Extract a module name based on the filename | ||
if (frame.filename) frame.module = getModule(frame.filename); | ||
// internal Node files are not full path names. Ignore them. | ||
if (isInternal) { | ||
frames[index] = frame; | ||
if (--callbacks === 0) cb(frames); | ||
return; | ||
if (frame.filename) { | ||
frame.module = getModule(frame.filename); | ||
if (!isInternal) filesToRead[frame.filename] = true; | ||
} | ||
if (frame.filename in cache) { | ||
parseLines(cache[frame.filename], frame); | ||
if (--callbacks === 0) cb(frames); | ||
return; | ||
} | ||
frames.push(frame); | ||
}); | ||
fs.readFile(frame.filename, function (_err, file) { | ||
if (!_err) { | ||
file = file.toString().split('\n'); | ||
cache[frame.filename] = file; | ||
parseLines(file, frame); | ||
return readSourceFiles(Object.keys(filesToRead), function (sourceFiles) { | ||
frames.forEach(function (frame) { | ||
if (frame.filename && sourceFiles[frame.filename]) { | ||
var lines = sourceFiles[frame.filename]; | ||
try { | ||
frame.pre_context = lines.slice(Math.max(0, frame.lineno - (LINES_OF_CONTEXT + 1)), frame.lineno - 1); | ||
frame.context_line = lines[frame.lineno - 1]; | ||
frame.post_context = lines.slice(frame.lineno, frame.lineno + LINES_OF_CONTEXT); | ||
} catch (e) { | ||
// anomaly, being defensive in case | ||
// unlikely to ever happen in practice but can definitely happen in theory | ||
} | ||
} | ||
frames[index] = frame; | ||
if (--callbacks === 0) cb(frames); | ||
}); | ||
cb(frames); | ||
}); | ||
@@ -216,0 +218,0 @@ } |
@@ -12,3 +12,3 @@ { | ||
], | ||
"version": "2.0.0", | ||
"version": "2.0.1", | ||
"repository": "git://github.com/getsentry/raven-node.git", | ||
@@ -35,5 +35,5 @@ "author": "Matt Robenolt <matt@ydekproductions.com>", | ||
"lsmod": "1.0.0", | ||
"uuid": "3.0.0", | ||
"stack-trace": "0.0.9", | ||
"timed-out": "4.0.1" | ||
"timed-out": "4.0.1", | ||
"uuid": "3.0.0" | ||
}, | ||
@@ -40,0 +40,0 @@ "devDependencies": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
50514
976