Skip to content

Commit

Permalink
fix nuget dependencies, bump esprima to 2.0.2, cleanup/fix readme
Browse files Browse the repository at this point in the history
  • Loading branch information
MaceWindu committed Jul 28, 2021
1 parent 6697ae9 commit 426fe08
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 86 deletions.
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<ItemGroup>
<PackageVersion Include="esprima" Version="2.0.0" />
<PackageVersion Include="esprima" Version="2.0.2" />
<PackageVersion Include="System.Text.Json" Version="5.0.2" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="1.0.0" />
<PackageVersion Include="NUnit3TestAdapter" Version="4.0.0" />
Expand Down
104 changes: 24 additions & 80 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,64 +4,15 @@ This is a C# library for working with JavaScript source maps and deminifying Jav

This is a fork of [microsoft/sourcemap-toolkit](https://github.com/microsoft/sourcemap-toolkit) project that solves following outstanding issues with original project:

- no active development is done anymore for original project
- no active development is done anymore for original project, mostly support-only changes for use inside MS teams
- no nuget publishing for recent changes: [#64](https://github.com/microsoft/sourcemap-toolkit/issues/64)
- lack of support for modern frameworks (.net core): [#57](https://github.com/microsoft/sourcemap-toolkit/issues/57)
- lack of support for ES6+: [#66](https://github.com/microsoft/sourcemap-toolkit/issues/66)

## Source Map Parsing
The `SourcemapTools.dll` provides an API for parsing a souce map into an object that is easy to work with and an API for serializing source map object back to json string.
The source map class has a method `GetMappingEntryForGeneratedSourcePosition`, which can be used to find a source map mapping entry that likely corresponds to a piece of generated code.
### Example
#### Source map string
```
{
"version": 3,
"file": "CommonIntl",
"mappings": "AACAA,aAAA,CAAc",
"sources": ["CommonIntl.js"],
"names": ["CommonStrings", "afrikaans"]
}
```
#### Sample source map object
|Name|Value|Type
|--- | --- | ---
|map&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|{SourcemapToolkit.SourcemapParser.SourceMap}|SourcemapToolkit.SourcemapParser.SourceMap
|&nbsp;\|--File|"CommonIntl"|string
|&nbsp;\|--Mappings|"AACAA,aAAA,CAAc"|string
|&nbsp;\|--Names|Count=2|System.Collections.Generic.List<string>
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--[0]|"CommonStrings"|string
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--[1]|"afrikaans"|string
|&nbsp;\|--ParsedMappings|Count=3|System.Collections.Generic.List<SourcemapToolkit.SourcemapParser.MappingEntry>
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--[0]|{SourcemapToolkit.SourcemapParser.MappingEntry}|SourcemapToolkit.SourcemapParser.MappingEntry
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--GeneratedSourcePosition|{SourcemapToolkit.SourcemapParser.SourcePosition}|SourcemapToolkit.SourcemapParser.SourcePosition
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--ZeroBasedColumnNumber|0|int
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--ZeroBasedLineNumber|0|int
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--OriginalFileName|"CommonIntl.js"|string
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--OriginalName|"CommonStrings"|string
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--OriginalSourcePosition|{SourcemapToolkit.SourcemapParser.SourcePosition}|SourcemapToolkit.SourcemapParser.SourcePosition
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--ZeroBasedColumnNumber|0|int
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--ZeroBasedLineNumber|1|int
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--[1]|{SourcemapToolkit.SourcemapParser.MappingEntry}|SourcemapToolkit.SourcemapParser.MappingEntry
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--GeneratedSourcePosition|{SourcemapToolkit.SourcemapParser.SourcePosition}|SourcemapToolkit.SourcemapParser.SourcePosition
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--ZeroBasedColumnNumber|13|int
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--ZeroBasedLineNumber|0|int
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--OriginalFileName|"CommonIntl.js"|string
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--OriginalName|null|string
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--OriginalSourcePosition|{SourcemapToolkit.SourcemapParser.SourcePosition}|SourcemapToolkit.SourcemapParser.SourcePosition
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--ZeroBasedColumnNumber|0|int
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--ZeroBasedLineNumber|1|int
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--[2]|{SourcemapToolkit.SourcemapParser.MappingEntry}|SourcemapToolkit.SourcemapParser.MappingEntry
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--GeneratedSourcePosition|{SourcemapToolkit.SourcemapParser.SourcePosition}|SourcemapToolkit.SourcemapParser.SourcePosition
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--ZeroBasedColumnNumber|14|int
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--ZeroBasedLineNumber|0|int
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--OriginalFileName|"CommonIntl.js"|string
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--OriginalName|null|string
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--OriginalSourcePosition|{SourcemapToolkit.SourcemapParser.SourcePosition}|SourcemapToolkit.SourcemapParser.SourcePosition
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--ZeroBasedColumnNumber|14|int
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--ZeroBasedLineNumber|1|int
|&nbsp;\|--Sources|Count=1|System.Collections.Generic.List<string>
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|--[0]|"CommonIntl.js"|string

### Usage
The top level API for source map parsing is the `SourceMapParser.ParseSourceMap` method. The input is a `Stream` that can be used to access the contents of the source map.
The top level API for source map serializing is the `SourceMapGenerator.SerializeMapping` method. The input is a `SourceMap` that to be serialized and an optional JsonSerializerSettings that can be used to control the json serialization.
Expand All @@ -70,7 +21,7 @@ A sample usage of the library is shown below.
```csharp
// Parse the source map from file
SourceMap sourceMap;
using (FileStream stream = new FileStream(@"sample.sourcemap", FileMode.Open))
using (var stream = new FileStream(@"sample.sourcemap", FileMode.Open))
{
sourceMap = SourceMapParser.ParseSourceMap(stream);
}
Expand All @@ -86,37 +37,30 @@ File.WriteAllText(@"updatedSample.sourcemap", serializedMap);
### Chaining source maps
A common use case when dealing with source maps is multiple mapping layers. You can use `ApplySourceMap` to chain maps together to link back to the source

```csharp
SourcePosition inOriginal = new SourcePosition { ZeroBasedLineNumber = 34, ZeroBasedColumnNumber = 23 };
SourcePosition inBundled = new SourcePosition { ZeroBasedLineNumber = 23, ZeroBasedColumnNumber = 12 };
SourcePosition inMinified = new SourcePosition { ZeroBasedLineNumber = 3, ZeroBasedColumnNumber = 2 };

MappingEntry originalToBundledEntry = new MappingEntry {
GeneratedSourcePosition = inBundled,
OriginalSourcePosition = inOriginal,
OriginalFileName = "original.js"
};

MappingEntry bundledToMinifiedEntry = new MappingEntry {
GeneratedSourcePosition = inMinified,
OriginalSourcePosition = inBundled,
OriginalFileName = "bundle.js"
};

SourceMap bundledToOriginal = new SourceMap {
```cs
var inOriginal = new SourcePosition(34, 23);
var inBundled = new SourcePosition(23, 12);
var inMinified = new SourcePosition(3 , 2 );

var originalToBundledEntry = new MappingEntry(inBundled, inOriginal, null, "original.js");
var bundledToMinifiedEntry = new MappingEntry(inMinified, inBundled, null, "bundle.js");

var bundledToOriginal = new SourceMap()
{
File = "bundled.js",
Sources = new List<string> { "original.js" },
ParsedMappings = new List<MappingEntry> { originalToBundledEntry }
ParsedMappings = new List<MappingEntry> { originalToBundledEntry }
}

SourceMap minifiedToBundled = new SourceMap {
var minifiedToBundled = new SourceMap()
{
File = "bundled.min.js",
Sources = new List<string> { "bundled.js" },
ParsedMappings = new List<MappingEntry> { bundledToMinifiedEntry }
}

// will contain mapping for line 3, column 2 in the minified file to line 34, column 23 in the original file
SourceMap minifiedToOriginal = minifiedToBundled.ApplySourceMap(bundledToOriginal);
var minifiedToOriginal = minifiedToBundled.ApplySourceMap(bundledToOriginal);
```

## Call Stack Deminification
Expand All @@ -135,23 +79,23 @@ TypeError: Cannot read property 'length' of undefined
```
FilePath: "http://localhost:11323/crashcauser.min.js"
MethodName: "i"
SourcePosition.ZeroBasedColumnNumber: 49
SourcePosition.ZeroBasedLineNumber: 0
SourcePosition.Column: 49
SourcePosition.Line: 0
```
#### Sample Deminified `StackFrame` entry
```
FilePath: "crashcauser.js"
MethodName: "level1"
SourcePosition.ZeroBasedColumnNumber: 8
SourcePosition.ZeroBasedLineNumber: 5
SourcePosition.Column: 8
SourcePosition.Line: 5
```
### Usage
The top level API for call stack deminification is the `StackTraceDeminifier.DeminifyStackTrace` method. For each url that appears in a JavaScript callstack, the library requires the contents of the JavaScript file and corresponding source map in order to determine the original method name and code location. This information is provided by the consumer of the API by implementing the `ISourceMapProvider` and `ISourceCodeProvider` interfaces. These interfaces are expected to return a `Stream` that can be used to access the contents of the requested JavaScript code or corresponding source map. A `StackTraceDeminifier` can be instantiated using one of the methods on `StackTraceDeminfierFactory`. A sample usage of the library is shown below.

```csharp
StackTraceDeminifier sourceMapCallstackDeminifier = StackTraceDeminifierFactory.GetStackTraceDeminfier(new SourceMapProvider(), new SourceCodeProvider());
DeminifyStackTraceResult deminifyStackTraceResult = sourceMapCallstackDeminifier.DeminifyStackTrace(callstack);
string deminifiedCallstack = deminifyStackTraceResult.ToString();
var sourceMapCallstackDeminifier = StackTraceDeminifierFactory.GetStackTraceDeminfier(new SourceMapProvider(), new SourceCodeProvider());
var deminifyStackTraceResult = sourceMapCallstackDeminifier.DeminifyStackTrace(callstack);
var deminifiedCallstack = deminifyStackTraceResult.ToString();
```

The result of `DeminifyStackTrace` is a `DeminifyStackTraceResult`, which is an object that contains a list of `StackFrameDeminificationResults` which contains the parsed minified `StackFrame` objects in the `MinifiedStackFrame` property and an enum indicating if any errors occured when attempting to deminify the `StackFrame`. The `DeminifiedStackFrame` property contains the best guess `StackFrame` object that maps to the `MinifiedStackFrame` element with the same index. Note that any of the properties on a `StackTrace` object may be null if no value could be extracted from the input callstack string or source map.
Expand Down
4 changes: 2 additions & 2 deletions ci/SourceMapTools.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

<dependencies>
<group targetFramework=".NETStandard2.0">
<dependency id="esprima" version="2.0.0-beta-1338" />
<dependency id="System.Text.Json" version="5.0.1" />
<dependency id="esprima" version="2.0.2" />
<dependency id="System.Text.Json" version="5.0.2" />
</group>
</dependencies>
</metadata>
Expand Down
4 changes: 2 additions & 2 deletions ci/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ variables:
- name: assemblyVersion
value: 1.0.0
- name: packageVersion
value: 1.0.0
value: 1.0.1
- name: nugetDevVersion
value: 1.0.0
value: 1.0.2

trigger:
- master
Expand Down
2 changes: 1 addition & 1 deletion src/SourceMapTools/SourcemapParser/SourcePosition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public struct SourcePosition : IComparable<SourcePosition>, IEquatable<SourcePos
/// <summary>
/// Unresolved stack frame postion token.
/// </summary>
public static readonly SourcePosition NotFound = new SourcePosition(-1, -1);
public static readonly SourcePosition NotFound = new (-1, -1);

/// <summary>
/// Zero-based position line number.
Expand Down

0 comments on commit 426fe08

Please sign in to comment.