stacktracey
Advanced tools
Comparing version 2.0.3 to 2.0.4
{ | ||
"name": "stacktracey", | ||
"version": "2.0.3", | ||
"version": "2.0.4", | ||
"description": "Parses call stacks. Reads sources. Clean & filtered output. Sourcemaps. Node & browsers.", | ||
@@ -5,0 +5,0 @@ "main": "stacktracey", |
@@ -13,3 +13,4 @@ # StackTracey | ||
- [x] Provides source text for call locations | ||
- [x] Fetches sources synchronously (even in browsers) via [get-source](https://github.com/xpl/get-source) | ||
- [x] Fetches sources (via [get-source](https://github.com/xpl/get-source)) | ||
- [x] Supports both asynchronous and synchronous interfaces (works even in browsers) | ||
- [x] Full sourcemap support | ||
@@ -79,3 +80,3 @@ - [x] Extracts useful information from `SyntaxError` instances | ||
Accessing sources: | ||
Accessing sources (**synchronously**, use with caution in browsers): | ||
@@ -87,2 +88,9 @@ ```javascript | ||
Accessing sources (**asynchronously**, preferred method in browsers): | ||
```javascript | ||
stack = await stack.withSourcesAsync () // returns a copy of stack with all items supplied with sources | ||
top = stack.items[0] // top item | ||
``` | ||
...or: | ||
@@ -93,2 +101,5 @@ | ||
``` | ||
```javascript | ||
top = await stack.withSourceAsyncAt (0) // supplies source for an individiual item (by index) | ||
``` | ||
@@ -100,2 +111,5 @@ ...or: | ||
``` | ||
```javascript | ||
top = await stack.withSourceAsync (stack.items[0]) // supplies source for an individiual item | ||
``` | ||
@@ -119,2 +133,4 @@ The returned items contain the following additional fields (already mapped through sourcemaps): | ||
Synchronously (use with caution in browsers): | ||
```javascript | ||
@@ -124,2 +140,8 @@ stack = stack.clean () | ||
...or (asynchronously): | ||
```javascript | ||
stack = await stack.cleanAsync () | ||
``` | ||
It does the following: | ||
@@ -132,2 +154,4 @@ | ||
You can customize its behavior by overriding the `isClean (entry, index)` predicate. | ||
## Custom `isThirdParty` Predicate | ||
@@ -134,0 +158,0 @@ |
@@ -56,9 +56,16 @@ declare interface SourceFile { | ||
withSourceAt (i: number): Entry | ||
withSourceAsyncAt (i: number): Promise<Entry> | ||
withSource (entry: Entry): Entry | ||
withSourceAsync (entry: Entry): Promise<Entry> | ||
withSources (): StackTracey | ||
withSourcesAsync (): Promise<StackTracey> | ||
mergeRepeatedLines (): StackTracey | ||
clean (): StackTracey | ||
cleanAsync (): StackTracey | ||
isClean (entry: Entry, index: number): boolean | ||
map (f: (x: Entry, i: number, arr: Entry[]) => Entry): StackTracey | ||
@@ -65,0 +72,0 @@ filter (f: (x: Entry, i: number, arr: Entry[]) => Entry): StackTracey |
@@ -74,3 +74,3 @@ "use strict"; | ||
extractEntryMetadata (e) { | ||
const fileRelative = this.relativePath (e.file || '') | ||
@@ -156,5 +156,9 @@ | ||
withSourceAsyncAt (i) { | ||
return this.items[i] && this.withSourceAsync (this.items[i]) | ||
} | ||
withSource (loc) { | ||
if (loc.sourceFile || (loc.file && loc.file.indexOf ('<') >= 0)) { // skip things like <anonymous> and stuff that was already fetched | ||
if (this.shouldSkipResolving (loc)) { | ||
return loc | ||
@@ -170,19 +174,41 @@ | ||
if (!resolved.sourceFile.error) { | ||
resolved.file = nixSlashes (resolved.sourceFile.path) | ||
resolved = this.extractEntryMetadata (resolved) | ||
} | ||
return this.withSourceResolved (loc, resolved) | ||
} | ||
} | ||
if (resolved.sourceLine.includes ('// @hide')) { | ||
resolved.sourceLine = resolved.sourceLine.replace ('// @hide', '') | ||
resolved.hide = true | ||
} | ||
withSourceAsync (loc) { | ||
if (this.shouldSkipResolving (loc)) { | ||
return Promise.resolve (loc) | ||
if (resolved.sourceLine.includes ('__webpack_require__') || // webpack-specific heuristics | ||
resolved.sourceLine.includes ('/******/ ({')) { | ||
resolved.thirdParty = true | ||
} | ||
} else { | ||
return getSource.async (loc.file || '') | ||
.then (x => x.resolve (loc)) | ||
.then (resolved => this.withSourceResolved (loc, resolved)) | ||
.catch (e => this.withSourceResolved (loc, { error: e, sourceLine: '' })) | ||
} | ||
} | ||
return O.assign ({ sourceLine: '' }, loc, resolved) | ||
shouldSkipResolving (loc) { | ||
return loc.sourceFile || (loc.file && loc.file.indexOf ('<') >= 0) // skip things like <anonymous> and stuff that was already fetched | ||
} | ||
withSourceResolved (loc, resolved) { | ||
if (resolved.sourceFile && !resolved.sourceFile.error) { | ||
resolved.file = nixSlashes (resolved.sourceFile.path) | ||
resolved = this.extractEntryMetadata (resolved) | ||
} | ||
if (resolved.sourceLine.includes ('// @hide')) { | ||
resolved.sourceLine = resolved.sourceLine.replace ('// @hide', '') | ||
resolved.hide = true | ||
} | ||
if (resolved.sourceLine.includes ('__webpack_require__') || // webpack-specific heuristics | ||
resolved.sourceLine.includes ('/******/ ({')) { | ||
resolved.thirdParty = true | ||
} | ||
return O.assign ({ sourceLine: '' }, loc, resolved) | ||
} | ||
@@ -194,2 +220,7 @@ | ||
withSourcesAsync () { | ||
return Promise.all (this.items.map (x => this.withSourceAsync (x))) | ||
.then (items => new StackTracey (items)) | ||
} | ||
mergeRepeatedLines () { | ||
@@ -210,7 +241,17 @@ return new StackTracey ( | ||
clean () { | ||
return this.withSources () | ||
.mergeRepeatedLines () | ||
.filter ((e, i) => (i === 0) || !(e.thirdParty || e.hide || e.native)) | ||
const s = this.withSources ().mergeRepeatedLines () | ||
return s.filter (s.isClean.bind (s)) | ||
} | ||
cleanAsync () { | ||
return this.withSourcesAsync ().then (s => { | ||
s = s.mergeRepeatedLines () | ||
return s.filter (s.isClean.bind (s)) | ||
}) | ||
} | ||
isClean (entry, index) { | ||
return (index === 0) || !(entry.thirdParty || entry.hide || entry.native) | ||
} | ||
at (i) { | ||
@@ -231,2 +272,3 @@ return O.assign ({ | ||
asTable (opts) { | ||
const maxColumnWidths = (opts && opts.maxColumnWidths) || this.maxColumnWidths () | ||
@@ -263,2 +305,3 @@ | ||
static locationsEqual (a, b) { | ||
return (a.file === b.file) && | ||
@@ -265,0 +308,0 @@ (a.line === b.line) && |
23
test.js
@@ -73,3 +73,24 @@ "use strict"; | ||
}) | ||
it ('allows to read sources (async)', () => { | ||
return shouldBeVisibleInStackTrace ().withSourcesAsync ().then (stack => { // @hide | ||
stack.should.be.an.instanceof (StackTracey) | ||
stack.items[0].beforeParse.should.not.be.undefined // should preserve previous fields | ||
stack.items[0].sourceLine.should.equal (' const shouldBeVisibleInStackTrace = () => new StackTracey () ') | ||
stack.items[0].hide.should.equal (true) // reads // @hide marker | ||
stack.items[1].hide.should.equal (true) // reads // @hide marker | ||
return stack.cleanAsync ().then (cleanStack => { | ||
cleanStack.should.be.an.instanceof (StackTracey) | ||
StackTracey.locationsEqual (cleanStack.items[0], stack.items[0]).should.equal (true) // should not clean top element | ||
StackTracey.locationsEqual (cleanStack.items[1], stack.items[1]).should.equal (false) // should clean second element (due to // @hide) | ||
}) | ||
}) | ||
}) | ||
it ('allows creation from array + groups duplicate lines', () => { | ||
@@ -76,0 +97,0 @@ |
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
41810
521
276