Source map apply (#52)
* Add POC source map unit tests * Implement apply source map * Modify tests * Remove combine maps * Remove ambiguous line tests. Add null test * Tabify files * Make tests more explicit. Add column info * Add a no matching mappings test * Updates to address code reviews * Remove ICloneable * Update README
This commit is contained in:
Родитель
b71be0f6f8
Коммит
e44bd1cd27
36
README.md
36
README.md
|
@ -77,6 +77,42 @@ string serializedMap = generator.SerializeMapping(sourceMap);
|
|||
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 {
|
||||
File = "bundled.js",
|
||||
Sources = new List<string> { "original.js" },
|
||||
ParsedMappings = new List<MappingEntry> { originalToBundledEntry }
|
||||
}
|
||||
|
||||
SourceMap 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);
|
||||
```
|
||||
|
||||
## Call Stack Deminification
|
||||
The `SourcemapToolkit.CallstackDeminifier.dll` allows for the deminification of JavaScript call stacks.
|
||||
### Example
|
||||
|
|
|
@ -1,25 +1,47 @@
|
|||
namespace SourcemapToolkit.SourcemapParser
|
||||
using System;
|
||||
|
||||
namespace SourcemapToolkit.SourcemapParser
|
||||
{
|
||||
public class MappingEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// The location of the line of code in the transformed code
|
||||
/// </summary>
|
||||
public SourcePosition GeneratedSourcePosition;
|
||||
public class MappingEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// The location of the line of code in the transformed code
|
||||
/// </summary>
|
||||
public SourcePosition GeneratedSourcePosition;
|
||||
|
||||
/// <summary>
|
||||
/// The location of the code in the original source code
|
||||
/// </summary>
|
||||
public SourcePosition OriginalSourcePosition;
|
||||
/// <summary>
|
||||
/// The location of the code in the original source code
|
||||
/// </summary>
|
||||
public SourcePosition OriginalSourcePosition;
|
||||
|
||||
/// <summary>
|
||||
/// The original name of the code referenced by this mapping entry
|
||||
/// </summary>
|
||||
public string OriginalName;
|
||||
/// <summary>
|
||||
/// The original name of the code referenced by this mapping entry
|
||||
/// </summary>
|
||||
public string OriginalName;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the file that originally contained this code
|
||||
/// </summary>
|
||||
public string OriginalFileName;
|
||||
}
|
||||
/// <summary>
|
||||
/// The name of the file that originally contained this code
|
||||
/// </summary>
|
||||
public string OriginalFileName;
|
||||
|
||||
public MappingEntry Clone()
|
||||
{
|
||||
return new MappingEntry
|
||||
{
|
||||
GeneratedSourcePosition = this.GeneratedSourcePosition as SourcePosition,
|
||||
OriginalSourcePosition = this.OriginalSourcePosition as SourcePosition,
|
||||
OriginalFileName = this.OriginalFileName,
|
||||
OriginalName = this.OriginalName
|
||||
};
|
||||
}
|
||||
|
||||
public Boolean IsValueEqual(MappingEntry anEntry)
|
||||
{
|
||||
return (
|
||||
this.OriginalName == anEntry.OriginalName &&
|
||||
this.OriginalFileName == anEntry.OriginalFileName &&
|
||||
this.GeneratedSourcePosition.CompareTo(anEntry.GeneratedSourcePosition) == 0 &&
|
||||
this.OriginalSourcePosition.CompareTo(anEntry.OriginalSourcePosition) == 0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SourcemapToolkit.SourcemapParser
|
||||
{
|
||||
|
@ -35,17 +36,94 @@ namespace SourcemapToolkit.SourcemapParser
|
|||
public List<MappingEntry> ParsedMappings;
|
||||
|
||||
/// <summary>
|
||||
/// Finds the mapping entry for the generated source position. If no exact match is found, it will attempt
|
||||
/// Applies the mappings of a sub source map to the current source map
|
||||
/// Each mapping to the supplied source file is rewritten using the supplied source map
|
||||
/// This is useful in situations where we have a to b to c, with mappings ba.map and cb.map
|
||||
/// Calling cb.ApplySourceMap(ba) will return mappings from c to a (ca)
|
||||
/// <param name="submap">The submap to apply</param>
|
||||
/// <param name="sourceFile">The filename of the source file. If not specified, submap's File property will be used</param>
|
||||
/// <returns>A new source map</returns>
|
||||
/// </summary>
|
||||
public SourceMap ApplySourceMap(SourceMap submap, string sourceFile = null)
|
||||
{
|
||||
if (submap == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(submap));
|
||||
}
|
||||
|
||||
if (sourceFile == null)
|
||||
{
|
||||
if (submap.File == null)
|
||||
{
|
||||
throw new Exception("ApplySourceMap expects either the explicit source file to the map, or submap's 'file' property");
|
||||
}
|
||||
|
||||
sourceFile = submap.File;
|
||||
}
|
||||
|
||||
SourceMap newSourceMap = new SourceMap
|
||||
{
|
||||
File = this.File,
|
||||
Version = this.Version,
|
||||
Sources = new List<string>(),
|
||||
Names = new List<string>(),
|
||||
ParsedMappings = new List<MappingEntry>()
|
||||
};
|
||||
|
||||
// transform mappings in this source map
|
||||
foreach (MappingEntry mappingEntry in this.ParsedMappings)
|
||||
{
|
||||
MappingEntry newMappingEntry = mappingEntry.Clone();
|
||||
|
||||
if (mappingEntry.OriginalFileName == sourceFile && mappingEntry.OriginalSourcePosition != null)
|
||||
{
|
||||
MappingEntry correspondingSubMapMappingEntry = submap.GetMappingEntryForGeneratedSourcePosition(mappingEntry.OriginalSourcePosition);
|
||||
|
||||
if (correspondingSubMapMappingEntry != null)
|
||||
{
|
||||
// Copy the mapping
|
||||
newMappingEntry = new MappingEntry
|
||||
{
|
||||
GeneratedSourcePosition = mappingEntry.GeneratedSourcePosition.Clone(),
|
||||
OriginalSourcePosition = correspondingSubMapMappingEntry.OriginalSourcePosition.Clone(),
|
||||
OriginalName = correspondingSubMapMappingEntry.OriginalName?? mappingEntry.OriginalName,
|
||||
OriginalFileName = correspondingSubMapMappingEntry.OriginalFileName?? mappingEntry.OriginalFileName
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Copy into "Sources" and "Names"
|
||||
string originalFileName = newMappingEntry.OriginalFileName;
|
||||
string originalName = newMappingEntry.OriginalName;
|
||||
|
||||
if (originalFileName != null && !newSourceMap.Sources.Contains(originalFileName))
|
||||
{
|
||||
newSourceMap.Sources.Add(originalFileName);
|
||||
}
|
||||
|
||||
if (originalName != null && !newSourceMap.Names.Contains(originalName))
|
||||
{
|
||||
newSourceMap.Names.Add(originalName);
|
||||
}
|
||||
|
||||
newSourceMap.ParsedMappings.Add(newMappingEntry);
|
||||
};
|
||||
|
||||
return newSourceMap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the mapping entry for the generated source position. If no exact match is found, it will attempt
|
||||
/// to return a nearby mapping that should map to the same piece of code.
|
||||
/// </summary>
|
||||
/// <param name="generatedSourcePosition">The location in generated code for which we want to discover a mapping entry</param>
|
||||
/// <returns>A mapping entry that is a close match for the desired generated code location</returns>
|
||||
public virtual MappingEntry GetMappingEntryForGeneratedSourcePosition(SourcePosition generatedSourcePosition)
|
||||
{
|
||||
if (ParsedMappings == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
public virtual MappingEntry GetMappingEntryForGeneratedSourcePosition(SourcePosition generatedSourcePosition)
|
||||
{
|
||||
if (ParsedMappings == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
MappingEntry mappingEntryToFind = new MappingEntry
|
||||
{
|
||||
|
@ -67,6 +145,6 @@ namespace SourcemapToolkit.SourcemapParser
|
|||
}
|
||||
|
||||
return index >= 0 ? ParsedMappings[index] : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,34 +2,34 @@
|
|||
|
||||
namespace SourcemapToolkit.SourcemapParser
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifies the location of a piece of code in a JavaScript file
|
||||
/// </summary>
|
||||
public class SourcePosition : IComparable<SourcePosition>
|
||||
{
|
||||
public int ZeroBasedLineNumber;
|
||||
/// <summary>
|
||||
/// Identifies the location of a piece of code in a JavaScript file
|
||||
/// </summary>
|
||||
public class SourcePosition : IComparable<SourcePosition>
|
||||
{
|
||||
public int ZeroBasedLineNumber;
|
||||
|
||||
public int ZeroBasedColumnNumber;
|
||||
public int ZeroBasedColumnNumber;
|
||||
|
||||
public int CompareTo(SourcePosition other)
|
||||
{
|
||||
if (this.ZeroBasedLineNumber == other.ZeroBasedLineNumber)
|
||||
{
|
||||
return this.ZeroBasedColumnNumber.CompareTo(other.ZeroBasedColumnNumber);
|
||||
}
|
||||
public int CompareTo(SourcePosition other)
|
||||
{
|
||||
if (this.ZeroBasedLineNumber == other.ZeroBasedLineNumber)
|
||||
{
|
||||
return this.ZeroBasedColumnNumber.CompareTo(other.ZeroBasedColumnNumber);
|
||||
}
|
||||
|
||||
return this.ZeroBasedLineNumber.CompareTo(other.ZeroBasedLineNumber);
|
||||
}
|
||||
return this.ZeroBasedLineNumber.CompareTo(other.ZeroBasedLineNumber);
|
||||
}
|
||||
|
||||
public static bool operator <(SourcePosition x, SourcePosition y)
|
||||
{
|
||||
return x.CompareTo(y) < 0;
|
||||
}
|
||||
public static bool operator <(SourcePosition x, SourcePosition y)
|
||||
{
|
||||
return x.CompareTo(y) < 0;
|
||||
}
|
||||
|
||||
public static bool operator >(SourcePosition x, SourcePosition y)
|
||||
{
|
||||
return x.CompareTo(y) > 0;
|
||||
}
|
||||
public static bool operator >(SourcePosition x, SourcePosition y)
|
||||
{
|
||||
return x.CompareTo(y) > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if we think that the two source positions are close enough together that they may in fact be the referring to the same piece of code.
|
||||
|
@ -57,5 +57,14 @@ namespace SourcemapToolkit.SourcemapParser
|
|||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public SourcePosition Clone()
|
||||
{
|
||||
return new SourcePosition
|
||||
{
|
||||
ZeroBasedLineNumber = this.ZeroBasedLineNumber,
|
||||
ZeroBasedColumnNumber = this.ZeroBasedColumnNumber
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
|
||||
namespace SourcemapToolkit.SourcemapParser.UnitTests
|
||||
{
|
||||
|
@ -11,7 +12,7 @@ namespace SourcemapToolkit.SourcemapParser.UnitTests
|
|||
{
|
||||
// Arrange
|
||||
SourceMap sourceMap = new SourceMap();
|
||||
SourcePosition sourcePosition = new SourcePosition {ZeroBasedColumnNumber = 3, ZeroBasedLineNumber = 4};
|
||||
SourcePosition sourcePosition = new SourcePosition {ZeroBasedColumnNumber = 3, ZeroBasedLineNumber = 4};
|
||||
|
||||
// Act
|
||||
MappingEntry result = sourceMap.GetMappingEntryForGeneratedSourcePosition(sourcePosition);
|
||||
|
@ -118,5 +119,270 @@ namespace SourcemapToolkit.SourcemapParser.UnitTests
|
|||
// Asset
|
||||
Assert.AreEqual(matchingMappingEntry, result);
|
||||
}
|
||||
}
|
||||
|
||||
private MappingEntry getSimpleEntry(SourcePosition generatedSourcePosition, SourcePosition originalSourcePosition, string originalFileName)
|
||||
{
|
||||
return new MappingEntry
|
||||
{
|
||||
GeneratedSourcePosition = generatedSourcePosition,
|
||||
OriginalSourcePosition = originalSourcePosition,
|
||||
OriginalFileName = originalFileName
|
||||
};
|
||||
}
|
||||
|
||||
private SourcePosition generateSourcePosition(int lineNumber, int colNumber = 0)
|
||||
{
|
||||
return new SourcePosition
|
||||
{
|
||||
ZeroBasedLineNumber = lineNumber,
|
||||
ZeroBasedColumnNumber = colNumber
|
||||
};
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetRootMappingEntryForGeneratedSourcePosition_NoChildren_ReturnsSameEntry()
|
||||
{
|
||||
// Arrange
|
||||
SourcePosition generated1 = generateSourcePosition(lineNumber:2, colNumber: 5);
|
||||
SourcePosition original1 = generateSourcePosition(lineNumber:1, colNumber: 5);
|
||||
MappingEntry mappingEntry = getSimpleEntry(generated1, original1, "generated.js");
|
||||
|
||||
SourceMap sourceMap = new SourceMap
|
||||
{
|
||||
Sources = new List<string> { "generated.js" },
|
||||
ParsedMappings = new List<MappingEntry> { mappingEntry }
|
||||
};
|
||||
|
||||
// Act
|
||||
MappingEntry rootEntry = sourceMap.GetMappingEntryForGeneratedSourcePosition(generated1);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(rootEntry, mappingEntry);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void ApplyMap_NullSubmap_ThrowsException()
|
||||
{
|
||||
// Arrange
|
||||
SourcePosition generated2 = generateSourcePosition(lineNumber:3, colNumber: 5);
|
||||
SourcePosition original2 = generateSourcePosition(lineNumber:2, colNumber: 5);
|
||||
MappingEntry mapping = getSimpleEntry(generated2, original2, "sourceOne.js");
|
||||
|
||||
SourceMap map = new SourceMap
|
||||
{
|
||||
File = "generated.js",
|
||||
Sources = new List<string> { "sourceOne.js" },
|
||||
ParsedMappings = new List<MappingEntry> { mapping }
|
||||
};
|
||||
|
||||
// Act
|
||||
SourceMap combinedMap = map.ApplySourceMap(null);
|
||||
|
||||
// Assert (decorated expected exception)
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ApplyMap_NoMatchingSources_ReturnsSameMap()
|
||||
{
|
||||
// Arrange
|
||||
SourcePosition generated1 = generateSourcePosition(lineNumber:2, colNumber: 3);
|
||||
SourcePosition original1 = generateSourcePosition(lineNumber:1, colNumber: 2);
|
||||
MappingEntry childMapping = getSimpleEntry(generated1, original1, "someOtherSource.js");
|
||||
|
||||
SourceMap childMap = new SourceMap
|
||||
{
|
||||
File = "notSourceOne.js",
|
||||
Sources = new List<string> { "someOtherSource.js" },
|
||||
ParsedMappings = new List<MappingEntry> { childMapping }
|
||||
};
|
||||
|
||||
SourcePosition generated2 = generateSourcePosition(lineNumber:3, colNumber: 7);
|
||||
SourcePosition original2 = generateSourcePosition(lineNumber:2, colNumber: 3);
|
||||
MappingEntry parentMapping = getSimpleEntry(generated2, original2, "sourceOne.js");
|
||||
|
||||
SourceMap parentMap = new SourceMap
|
||||
{
|
||||
File = "generated.js",
|
||||
Sources = new List<string> { "sourceOne.js" },
|
||||
ParsedMappings = new List<MappingEntry> { parentMapping }
|
||||
};
|
||||
|
||||
// Act
|
||||
SourceMap combinedMap = parentMap.ApplySourceMap(childMap);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(combinedMap);
|
||||
MappingEntry firstMapping = combinedMap.ParsedMappings[0];
|
||||
Assert.IsTrue(firstMapping.IsValueEqual(parentMapping));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ApplyMap_NoMatchingMappings_ReturnsSameMap()
|
||||
{
|
||||
// Arrange
|
||||
SourcePosition generated1 = generateSourcePosition(lineNumber: 2, colNumber:2);
|
||||
SourcePosition original1 = generateSourcePosition(lineNumber: 1, colNumber:10);
|
||||
MappingEntry childMapping = getSimpleEntry(generated1, original1, "sourceTwo.js");
|
||||
|
||||
SourceMap childMap = new SourceMap
|
||||
{
|
||||
File = "sourceOne.js",
|
||||
Sources = new List<string> { "sourceTwo.js" },
|
||||
ParsedMappings = new List<MappingEntry> { childMapping }
|
||||
};
|
||||
|
||||
SourcePosition generated2 = generateSourcePosition(lineNumber:3, colNumber:4);
|
||||
SourcePosition original2 = generateSourcePosition(lineNumber:2, colNumber:5);
|
||||
MappingEntry parentMapping = getSimpleEntry(generated2, original2, "sourceOne.js");
|
||||
|
||||
SourceMap parentMap = new SourceMap
|
||||
{
|
||||
File = "generated.js",
|
||||
Sources = new List<string> { "sourceOne.js" },
|
||||
ParsedMappings = new List<MappingEntry> { parentMapping }
|
||||
};
|
||||
|
||||
// Act
|
||||
SourceMap combinedMap = parentMap.ApplySourceMap(childMap);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(combinedMap);
|
||||
MappingEntry firstMapping = combinedMap.ParsedMappings[0];
|
||||
Assert.IsTrue(firstMapping.IsValueEqual(parentMapping));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ApplyMap_MatchingSources_ReturnsCorrectMap()
|
||||
{
|
||||
// Expect mapping with same source filename as the applied source-map to be replaced
|
||||
|
||||
// Arrange
|
||||
SourcePosition generated1 = generateSourcePosition(lineNumber:2, colNumber:4);
|
||||
SourcePosition original1 = generateSourcePosition(lineNumber:1, colNumber:3);
|
||||
MappingEntry childMapping = getSimpleEntry(generated1, original1, "sourceTwo.js");
|
||||
|
||||
SourceMap childMap = new SourceMap
|
||||
{
|
||||
File = "sourceOne.js",
|
||||
Sources = new List<string> { "sourceTwo.js" },
|
||||
ParsedMappings = new List<MappingEntry> { childMapping }
|
||||
};
|
||||
|
||||
SourcePosition generated2 = generateSourcePosition(lineNumber:3, colNumber: 5);
|
||||
SourcePosition original2 = generateSourcePosition(lineNumber:2, colNumber: 4);
|
||||
MappingEntry parentMapping = getSimpleEntry(generated2, original2, "sourceOne.js");
|
||||
|
||||
SourceMap parentMap = new SourceMap
|
||||
{
|
||||
File = "generated.js",
|
||||
Sources = new List<string> { "sourceOne.js" },
|
||||
ParsedMappings = new List<MappingEntry> { parentMapping }
|
||||
};
|
||||
|
||||
// Act
|
||||
SourceMap combinedMap = parentMap.ApplySourceMap(childMap);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(combinedMap);
|
||||
Assert.AreEqual(1, combinedMap.ParsedMappings.Count);
|
||||
Assert.AreEqual(1, combinedMap.Sources.Count);
|
||||
MappingEntry rootMapping = combinedMap.GetMappingEntryForGeneratedSourcePosition(generated2);
|
||||
Assert.AreEqual(0, rootMapping.OriginalSourcePosition.CompareTo(childMapping.OriginalSourcePosition));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ApplyMap_PartialMatchingSources_ReturnsCorrectMap()
|
||||
{
|
||||
// Expect mappings with same source filename as the applied source-map to be replaced
|
||||
// mappings with a different source filename should stay the same
|
||||
|
||||
// Arrange
|
||||
SourcePosition generated1 = generateSourcePosition(lineNumber:2, colNumber:10);
|
||||
SourcePosition original1 = generateSourcePosition(lineNumber:1, colNumber:5);
|
||||
MappingEntry childMapping = getSimpleEntry(generated1, original1, "sourceTwo.js");
|
||||
|
||||
SourceMap childMap = new SourceMap
|
||||
{
|
||||
File = "sourceOne.js",
|
||||
Sources = new List<string> { "sourceTwo.js" },
|
||||
ParsedMappings = new List<MappingEntry> { childMapping }
|
||||
};
|
||||
|
||||
SourcePosition generated2 = generateSourcePosition(lineNumber:3, colNumber:2);
|
||||
SourcePosition original2 = generateSourcePosition(lineNumber:2, colNumber: 10);
|
||||
MappingEntry mapping = getSimpleEntry(generated2, original2, "sourceOne.js");
|
||||
|
||||
SourcePosition generated3 = generateSourcePosition(lineNumber:4, colNumber:3);
|
||||
SourcePosition original3 = generateSourcePosition(lineNumber:3, colNumber:2);
|
||||
MappingEntry mapping2 = getSimpleEntry(generated3, original3, "noMapForThis.js");
|
||||
|
||||
SourceMap parentMap = new SourceMap
|
||||
{
|
||||
File = "generated.js",
|
||||
Sources = new List<string> { "sourceOne.js", "noMapForThis.js" },
|
||||
ParsedMappings = new List<MappingEntry> { mapping, mapping2 }
|
||||
};
|
||||
|
||||
// Act
|
||||
SourceMap combinedMap = parentMap.ApplySourceMap(childMap);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(combinedMap);
|
||||
Assert.AreEqual(2, combinedMap.ParsedMappings.Count);
|
||||
Assert.AreEqual(2, combinedMap.Sources.Count);
|
||||
MappingEntry firstCombinedMapping = combinedMap.GetMappingEntryForGeneratedSourcePosition(generated3);
|
||||
Assert.IsTrue(firstCombinedMapping.IsValueEqual(mapping2));
|
||||
MappingEntry secondCombinedMapping = combinedMap.GetMappingEntryForGeneratedSourcePosition(generated2);
|
||||
Assert.AreEqual(0, secondCombinedMapping.OriginalSourcePosition.CompareTo(childMapping.OriginalSourcePosition));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ApplyMap_ExactMatchDeep_ReturnsCorrectMappingEntry()
|
||||
{
|
||||
// Arrange
|
||||
SourcePosition generated1 = generateSourcePosition(lineNumber:3, colNumber:5);
|
||||
SourcePosition original1 = generateSourcePosition(lineNumber:2, colNumber:10);
|
||||
MappingEntry mapLevel2 = getSimpleEntry(generated1, original1, "sourceThree.js");
|
||||
|
||||
SourceMap grandChildMap = new SourceMap
|
||||
{
|
||||
File = "sourceTwo.js",
|
||||
Sources = new List<string> { "sourceThree.js" },
|
||||
ParsedMappings = new List<MappingEntry> { mapLevel2 }
|
||||
};
|
||||
|
||||
SourcePosition generated2 = generateSourcePosition(lineNumber:4, colNumber:3);
|
||||
SourcePosition original2 = generateSourcePosition(lineNumber:3, colNumber:5);
|
||||
MappingEntry mapLevel1 = getSimpleEntry(generated2, original2, "sourceTwo.js");
|
||||
|
||||
SourceMap childMap = new SourceMap
|
||||
{
|
||||
File = "sourceOne.js",
|
||||
Sources = new List<string> { "sourceTwo.js" },
|
||||
ParsedMappings = new List<MappingEntry> { mapLevel1 }
|
||||
};
|
||||
|
||||
SourcePosition generated3 = generateSourcePosition(lineNumber:5, colNumber:5);
|
||||
SourcePosition original3 = generateSourcePosition(lineNumber:4, colNumber:3);
|
||||
MappingEntry mapLevel0 = getSimpleEntry(generated3, original3, "sourceOne.js");
|
||||
|
||||
SourceMap parentMap = new SourceMap
|
||||
{
|
||||
File = "generated.js",
|
||||
Sources = new List<string> { "sourceOne.js" },
|
||||
ParsedMappings = new List<MappingEntry> { mapLevel0 }
|
||||
};
|
||||
|
||||
// Act
|
||||
SourceMap firstCombinedMap = parentMap.ApplySourceMap(childMap);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(firstCombinedMap);
|
||||
SourceMap secondCombinedMap = firstCombinedMap.ApplySourceMap(grandChildMap);
|
||||
Assert.IsNotNull(secondCombinedMap);
|
||||
MappingEntry rootMapping = secondCombinedMap.GetMappingEntryForGeneratedSourcePosition(generated3);
|
||||
Assert.AreEqual(0, rootMapping.OriginalSourcePosition.CompareTo(mapLevel2.OriginalSourcePosition));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,6 +80,16 @@
|
|||
<Name>SourcemapToolkit.SourcemapParser</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="child1.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="child1.js.map">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||
<ItemGroup>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
//# sourceMappingURL=child1.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["source.js"],"names":[],"mappings":";AAAA","file":"child1.js"}
|
Загрузка…
Ссылка в новой задаче