Created
April 5, 2018 17:21
-
-
Save treeform/c95e4073a6f5942d8192a4d425cb885f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import json | |
| import strutils | |
| type | |
| Mapping = object | |
| generatedLine: int | |
| generatedColumn: int | |
| originalLine: int | |
| originalColumn: int | |
| source: string | |
| name: string | |
| SourceMap = ref object | |
| file: string | |
| mappings: seq[Mapping] | |
| sources: seq[string] | |
| names: seq[string] | |
| proc newSourceMap(file: string): SourceMap = | |
| result = new SourceMap | |
| result.file = file | |
| result.mappings = newSeq[Mapping]() | |
| result.sources = newSeq[string]() | |
| result.names = newSeq[string]() | |
| proc compareByGeneratedPositionsInflated(mappingA, mappingB: Mapping): int = | |
| var cmp = mappingA.generatedLine - mappingB.generatedLine; | |
| if cmp != 0: | |
| return cmp | |
| cmp = mappingA.generatedColumn - mappingB.generatedColumn; | |
| if cmp != 0: | |
| return cmp; | |
| cmp = cmp(mappingA.source, mappingB.source); | |
| if cmp != 0: | |
| return cmp; | |
| cmp = mappingA.originalLine - mappingB.originalLine; | |
| if cmp != 0: | |
| return cmp | |
| cmp = mappingA.originalColumn - mappingB.originalColumn; | |
| if cmp != 0: | |
| return cmp | |
| return cmp(mappingA.name, mappingB.name); | |
| const | |
| VLQ_BASE_SHIFT = 5 | |
| # binary: 100000 | |
| VLQ_BASE = 1 shl VLQ_BASE_SHIFT | |
| #binary: 011111 | |
| VLQ_BASE_MASK = VLQ_BASE - 1 | |
| # binary: 100000 | |
| VLQ_CONTINUATION_BIT = VLQ_BASE | |
| proc toVLQSigned(aValue: int): int = | |
| if aValue < 0: | |
| ((-aValue) shl 1) + 1 | |
| else: | |
| (aValue shl 1) + 0; | |
| assert toVLQSigned(1) == 2 | |
| assert toVLQSigned(2) == 4 | |
| assert toVLQSigned(-1) == 3 | |
| assert toVLQSigned(-2) == 5 | |
| assert toVLQSigned(0) == 0 | |
| const intToCharMap = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" | |
| proc digit64encode(digit: int): char = | |
| ## Encode an integer in the range of 0 to 63 to a single base 64 digit. | |
| assert 0 <= digit or digit < intToCharMap.len, "digit out of range" | |
| return intToCharMap[digit] | |
| assert digit64encode(0) == 'A' | |
| assert digit64encode(13) == 'N' | |
| proc base64VLQencode(aValue: int): string = | |
| var encoded = "" | |
| var digit = 0 | |
| var vlq = toVLQSigned(aValue) | |
| while true: | |
| #echo "hi", vlq, digit, encoded | |
| #digit = vlq & VLQ_BASE_MASK; | |
| #vlq >>>= VLQ_BASE_SHIFT; | |
| digit = vlq and VLQ_BASE_MASK | |
| vlq = vlq shr VLQ_BASE_SHIFT | |
| if vlq > 0: | |
| # There are still more digits in this value, so we must make sure the | |
| # continuation bit is marked. | |
| digit = digit or VLQ_CONTINUATION_BIT | |
| encoded &= digit64encode(digit) | |
| #echo encoded | |
| if not (vlq > 0): | |
| break | |
| return encoded | |
| assert base64VLQencode(1) == "C" | |
| assert base64VLQencode(-1) == "D" | |
| assert base64VLQencode(98) == "kG" | |
| proc serializeMappings(sourceMap: SourceMap): string = | |
| # update the source arrays | |
| for i, mapping in sourceMap.mappings: | |
| if mapping.source != nil: | |
| let sourceIdx = sourceMap.sources.find(mapping.source) | |
| if sourceIdx == -1: | |
| sourceMap.sources.add(mapping.source) | |
| # update the name arrays | |
| for i, mapping in sourceMap.mappings: | |
| if mapping.name != nil: | |
| let nameIdx = sourceMap.names.find(mapping.name) | |
| if nameIdx == -1: | |
| sourceMap.names.add(mapping.name) | |
| result = "" | |
| var | |
| previousGeneratedColumn = 0 | |
| previousGeneratedLine = 1 | |
| previousOriginalColumn = 0 | |
| previousOriginalLine = 0 | |
| previousName = 0 | |
| previousSource = 0 | |
| next = "" | |
| nameIdx: int | |
| sourceIdx: int | |
| for i, mapping in sourceMap.mappings: | |
| #echo mapping | |
| if mapping.generatedLine != previousGeneratedLine: | |
| previousGeneratedColumn = 0 | |
| while mapping.generatedLine != previousGeneratedLine: | |
| next &= ';' | |
| inc previousGeneratedLine | |
| else: | |
| if i > 0: | |
| if compareByGeneratedPositionsInflated(mapping, sourceMap.mappings[i - 1]) != 0: | |
| continue | |
| next &= ',' | |
| next &= base64VLQencode(mapping.generatedColumn - previousGeneratedColumn) | |
| previousGeneratedColumn = mapping.generatedColumn | |
| if mapping.source != nil: | |
| sourceIdx = sourceMap.sources.find(mapping.source) | |
| next &= base64VLQencode(sourceIdx - previousSource) | |
| previousSource = sourceIdx | |
| # lines are stored 0-based in SourceMap spec version 3 | |
| next &= base64VLQencode(mapping.originalLine - 1 - previousOriginalLine) | |
| previousOriginalLine = mapping.originalLine - 1 | |
| next &= base64VLQencode(mapping.originalColumn - previousOriginalColumn) | |
| previousOriginalColumn = mapping.originalColumn | |
| result &= next | |
| proc toJson(sourceMap: SourceMap): JsonNode = | |
| let serializedMappings = sourceMap.serializeMappings() | |
| return %* { | |
| "version": 3, | |
| "sources": sourceMap.sources, | |
| "names": sourceMap.names, | |
| "mappings": serializedMappings, | |
| "file": sourceMap.file, | |
| } | |
| var s = newSourceMap("test.js.map") | |
| #[ | |
| s.mappings.add Mapping( | |
| source: "test.nim", | |
| originalLine: 1, | |
| originalColumn: 1, | |
| generatedLine: 79, | |
| generatedColumn: 1 | |
| ) | |
| s.mappings.add Mapping( | |
| source: "test.nim", | |
| originalLine: 2, | |
| originalColumn: 2, | |
| generatedLine: 82, | |
| generatedColumn: 5 | |
| ) | |
| s.mappings.add Mapping( | |
| source: "test.nim", | |
| originalLine: 3, | |
| originalColumn: 2, | |
| generatedLine: 84, | |
| generatedColumn: 5 | |
| ) | |
| s.mappings.add Mapping( | |
| source: "test.nim", | |
| originalLine: 4, | |
| originalColumn: 2, | |
| generatedLine: 86, | |
| generatedColumn: 5 | |
| ) | |
| s.mappings.add Mapping( | |
| source: "test.nim", | |
| originalLine: 5, | |
| originalColumn: 4, | |
| generatedLine: 87, | |
| generatedColumn: 5 | |
| ) | |
| s.mappings.add Mapping( | |
| source: "test.nim", | |
| originalLine: 7, | |
| originalColumn: 1, | |
| generatedLine: 95, | |
| generatedColumn: 1 | |
| ) | |
| ]# |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment