backtracker
Advanced tools
Comparing version 3.1.4 to 3.2.0
@@ -1,13 +0,22 @@ | ||
import Caller from "./Caller"; | ||
import Frame from "./Frame"; | ||
import Stack from "./Stack"; | ||
declare class BackTracker { | ||
parent: Caller; | ||
parent: Frame; | ||
constructor(); | ||
static get stack(): Stack; | ||
/** | ||
* Process an Array of strings from an Error stack. The strings must be trimmed as the regular expressions specify string start and end. | ||
* You can easily get what's required for this by doing the example provided. | ||
* | ||
* The slice is necessary because the Error name and message is included in the first line of the stack | ||
* @param withParentReferences If each stack frame should have references to the previous frame added to itself | ||
* @example BackTracker.process(new Error().stack.split("\n").slice(1).map(i => i.trim())) | ||
*/ | ||
static process(frames: Array<string>, withParentReferences?: boolean): Stack; | ||
} | ||
declare const _default: { | ||
BackTracker: typeof BackTracker; | ||
Caller: typeof Caller; | ||
Frame: typeof Frame; | ||
Stack: typeof Stack; | ||
}; | ||
export = _default; |
@@ -5,11 +5,9 @@ "use strict"; | ||
}; | ||
const Caller_1 = __importDefault(require("./Caller")); | ||
const Frame_1 = __importDefault(require("./Frame")); | ||
const Stack_1 = __importDefault(require("./Stack")); | ||
const [evalreg, namedreg, anonymousreg, notnamedreg, somethingreg, filereg] = [ | ||
/at eval \(eval at ([\w_.<>]*) \(([^*?"<>]*):(\d+):(\d+)\),? ?(?:[^:]+:\d+:\d+)?\)/, | ||
/at (async)? ?([\w_.<>]+)? \(([^*?"<>]*):(\d+):(\d+)\)/, | ||
/at (.[\w_.<>]*)? ?\((<anonymous>)\)/, | ||
/at ([^*?"<>]*):(\d+):(\d+)/, | ||
/((?:.[\w_.<>]*)? ?(?:.[\w_.<>]*)? ?\[(?:as)? ?(?:.[\w_.<>]*)\])? ?\(([^*?"<>]*):(\d+):(\d+)\)/, | ||
/at (async)? ?file:\/\/\/([\w\d:\/\. \(\)_\-,]+):(\d+):(\d+)/ // expression for file urls | ||
const [evalreg, anonymousreg, pallreg, scopereg] = [ | ||
/^at eval \(eval a?t? ?([\w_\.<>]+)? ?\((?:file\:\/\/\/)?([^*"\)]+):(\d+):(\d+)\),? ?([\w_\.<>]+)?:\d+:\d+\)$/, | ||
/^at ([\w_\.<>]+)? ?\(?<anonymous>\)?$/, | ||
/^at (?:async)? ?Promise.all \(index (\d+)\)$/, | ||
/^at (async)? ?((?!\bfile\b|[A-Z]:)[\w_\.<> ]+)? ?(?:\[as ([\w_\.<> ]+)\])? ?\(?(?:file\:\/\/\/)?([^*"]+):(\d+):(\d+)\)?$/, // expression for named and unnamed scopes including functions that were renamed as well as getters | ||
]; | ||
@@ -23,46 +21,50 @@ class BackTracker { | ||
const stack = new Error().stack; | ||
const callers = new Stack_1.default(); | ||
if (!stack) { | ||
callers.push(new Caller_1.default({ path: __dirname || "backtracker:internal/index", async: false, scope: "root", line: 0, column: 0, anonymous: true })); | ||
return callers; | ||
const stackframes = new Stack_1.default(); | ||
stackframes.push(new Frame_1.default({ path: __dirname || "backtracker:internal/index", async: false, scope: "stack", line: 22, column: 7, anonymous: false })); | ||
return stackframes; | ||
} | ||
const split = stack.split("\n"); | ||
const frames = split.slice(3, split.length).map(item => item.trim()); | ||
const frames = split.slice(3).map(item => item.trim()); // slice out the first 3 lines which is the Error message, BackTracker's frame, and the current frame which leaves you with the previous as the current is known | ||
return BackTracker.process(frames); | ||
} | ||
/** | ||
* Process an Array of strings from an Error stack. The strings must be trimmed as the regular expressions specify string start and end. | ||
* You can easily get what's required for this by doing the example provided. | ||
* | ||
* The slice is necessary because the Error name and message is included in the first line of the stack | ||
* @param withParentReferences If each stack frame should have references to the previous frame added to itself | ||
* @example BackTracker.process(new Error().stack.split("\n").slice(1).map(i => i.trim())) | ||
*/ | ||
static process(frames, withParentReferences = true) { | ||
const stackframes = new Stack_1.default(); | ||
for (const frame of frames) { | ||
const test1 = evalreg.exec(frame); | ||
const test6 = filereg.exec(frame); | ||
if (test6 && test6.length > 0) { | ||
callers.push(new Caller_1.default({ path: test6[2], async: !!test6[1], scope: "file", line: Number(test6[3]), column: Number(test6[4]), anonymous: false })); | ||
if (test1 && test1.length) { | ||
stackframes.push(new Frame_1.default({ path: test1[2], async: false, scope: test1[1], line: Number(test1[3]), column: Number(test1[4]), anonymous: (!!test1[5] && test1[5].includes("<anonymous>")) })); | ||
continue; | ||
} | ||
if (test1 && test1.length > 0) { | ||
callers.push(new Caller_1.default({ path: test1[2], async: false, scope: test1[1], line: Number(test1[3]), column: Number(test1[4]), anonymous: !!test1[5] })); | ||
const test2 = anonymousreg.exec(frame); | ||
if (test2 && test2.length) { | ||
stackframes.push(new Frame_1.default({ path: test2[2], async: false, scope: test2[1], line: 0, column: 0, anonymous: true })); | ||
continue; | ||
} | ||
const test2 = somethingreg.exec(frame); | ||
if (test2 && test2.length > 0) { | ||
callers.push(new Caller_1.default({ path: test2[2], async: false, scope: test2[1], line: Number(test2[3]), column: Number(test2[4]), anonymous: false })); | ||
const test3 = pallreg.exec(frame); | ||
if (test3 && test3.length) { | ||
stackframes.push(new Frame_1.default({ path: "node:v8/promise-all", async: true, scope: `Promise.all index ${test3[1] || 0}`, line: 0, column: 0, anonymous: false })); | ||
continue; | ||
} | ||
const test3 = namedreg.exec(frame); | ||
if (test3 && test3.length > 0) { | ||
callers.push(new Caller_1.default({ path: test3[3], async: !!test3[1], scope: test3[2], line: Number(test3[4]), column: Number(test3[5]), anonymous: false })); | ||
const test4 = scopereg.exec(frame); | ||
if (test4 && test4.length) { | ||
stackframes.push(new Frame_1.default({ path: test4[4], async: !!test4[1], scope: test4[2] ? `${test4[2].trim()}${test4[3] ? `as ${test4[3]}` : ""}` : "unknown", line: Number(test4[5]), column: Number(test4[6]), anonymous: (!!test4[2] && test4[2].includes("<anonymous>")) })); | ||
continue; | ||
} | ||
const test4 = anonymousreg.exec(frame); | ||
if (test4 && test4.length > 0) { | ||
callers.push(new Caller_1.default({ path: test4[2], async: false, scope: test4[1], line: 0, column: 0, anonymous: true })); | ||
continue; | ||
} | ||
if (withParentReferences) { | ||
for (const f of stackframes) { | ||
const index = stackframes.indexOf(f); | ||
f.parent = stackframes[index + 1] || null; | ||
} | ||
const test5 = notnamedreg.exec(frame); | ||
if (test5 && test5.length > 0) { | ||
callers.push(new Caller_1.default({ path: test5[1], async: false, scope: "root", line: Number(test5[2]), column: Number(test5[3]), anonymous: false })); | ||
continue; | ||
} | ||
} | ||
for (const caller of callers) { | ||
const index = callers.indexOf(caller); | ||
caller.parent = callers[index + 1] ? callers[index + 1] : null; | ||
} | ||
return callers; | ||
return stackframes; | ||
} | ||
@@ -72,4 +74,4 @@ } | ||
BackTracker, | ||
Caller: Caller_1.default, | ||
Frame: Frame_1.default, | ||
Stack: Stack_1.default | ||
}; |
@@ -1,8 +0,8 @@ | ||
declare class Stack extends Array<import("./Caller")> { | ||
declare class Stack extends Array<import("./Frame")> { | ||
constructor(); | ||
first(): import("./Caller"); | ||
first(amount: number): Array<import("./Caller")>; | ||
last(): import("./Caller"); | ||
last(amount: number): Array<import("./Caller")>; | ||
first(): import("./Frame"); | ||
first(amount: number): Array<import("./Frame")>; | ||
last(): import("./Frame"); | ||
last(amount: number): Array<import("./Frame")>; | ||
} | ||
export = Stack; |
{ | ||
"name": "backtracker", | ||
"version": "3.1.4", | ||
"version": "3.2.0", | ||
"description": "Back track in JS code execution and find where a function was called", | ||
@@ -17,3 +17,3 @@ "main": "dist/index", | ||
"back-tracker", | ||
"back" | ||
"errors" | ||
], | ||
@@ -20,0 +20,0 @@ "author": "PapiOphidian", |
@@ -10,3 +10,3 @@ # BackTracker | ||
# Contributing | ||
If you would like to contribute and modify the regular expressions, please open a Pull Request and I will test code changes against a dataset of stack frames including stack frames which you might want to add support for. | ||
If you would like to contribute and modify the regular expressions, please open a Pull Request and I will test code changes against a dataset of stack frames I have and including stack frames which you might want to add support for. | ||
@@ -17,3 +17,3 @@ # Examples | ||
```js | ||
const BackTracker = require("backtracker").BackTracker; | ||
const { BackTracker } = require("backtracker"); | ||
@@ -40,8 +40,7 @@ function epic() { | ||
starting index.js logs the following | ||
``` | ||
C:\Users\papi\Documents\GitHub\BackTracker>node example/index.js | ||
Not epic at all | ||
Okay. This is epic. | ||
Caller { | ||
Output example: | ||
```js | ||
'Not epic at all' | ||
'Okay. This is epic.' | ||
Frame { | ||
path: 'C:\\Users\\papi\\Documents\\GitHub\\BackTracker\\example\\index.js', | ||
@@ -51,7 +50,7 @@ dir: 'C:\\Users\\papi\\Documents\\GitHub\\BackTracker\\example', | ||
async: false, | ||
scope: undefined, | ||
scope: 'notEpic', | ||
line: 5, | ||
column: 2, | ||
anonymous: false, | ||
parent: Caller { | ||
parent: Frame { | ||
path: 'C:\\Users\\papi\\Documents\\GitHub\\BackTracker\\example\\index.js', | ||
@@ -61,16 +60,16 @@ dir: 'C:\\Users\\papi\\Documents\\GitHub\\BackTracker\\example', | ||
async: false, | ||
scope: undefined, | ||
scope: 'Object.<anonymous>', | ||
line: 8, | ||
column: 1, | ||
anonymous: false, | ||
parent: Caller { | ||
path: 'internal/modules/cjs/loader.js', | ||
dir: 'internal/modules/cjs', | ||
filename: 'loader.js', | ||
anonymous: true, | ||
parent: Frame { | ||
path: 'node:internal/modules/cjs/loader', | ||
dir: 'node:internal/modules/cjs', | ||
filename: 'loader', | ||
async: false, | ||
scope: undefined, | ||
line: 936, | ||
column: 30, | ||
scope: 'Module._compile', | ||
line: 1095, | ||
column: 14, | ||
anonymous: false, | ||
parent: [Caller] | ||
parent: [Frame] | ||
} | ||
@@ -77,0 +76,0 @@ } |
Sorry, the diff of this file is not supported yet
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
30616
11
229
74