Index: pkg/source_maps/lib/parser.dart |
diff --git a/pkg/source_maps/lib/parser.dart b/pkg/source_maps/lib/parser.dart |
index c92a8bba0ba917699ae7ffa516f2c1740db296ef..9f70d23a3c537c3a1fec05e0f1e9b8f9b3bd29c8 100644 |
--- a/pkg/source_maps/lib/parser.dart |
+++ b/pkg/source_maps/lib/parser.dart |
@@ -5,8 +5,10 @@ |
/// Contains the top-level function to parse source maps version 3. |
library source_maps.parser; |
+import 'dart:collection'; |
import 'dart:convert'; |
+import 'builder.dart'; |
import 'span.dart'; |
import 'src/utils.dart'; |
import 'src/vlq.dart'; |
@@ -41,7 +43,7 @@ Mapping parseJson(Map map, {Map<String, Map> otherMaps}) { |
} |
-/// A mapping parsed our of a source map. |
+/// A mapping parsed out of a source map. |
abstract class Mapping { |
Span spanFor(int line, int column, {Map<String, SourceFile> files}); |
@@ -145,6 +147,46 @@ class SingleMapping extends Mapping { |
/// Entries indicating the beginning of each span. |
final List<TargetLineEntry> lines = <TargetLineEntry>[]; |
+ SingleMapping._internal(this.targetUrl, this.urls, this.names); |
+ |
+ factory SingleMapping.fromBuilder(SourceMapBuilder builder, [String fileUrl]) { |
Siggi Cherem (dart-lang)
2014/07/08 00:31:01
how about switching to take a list of entries inst
tjblasi
2014/07/08 16:36:20
Done.
|
+ List<Entry> sourceEntries = builder.entries; |
+ List<TargetLineEntry> lines = []; |
Siggi Cherem (dart-lang)
2014/07/08 00:31:01
style nit: use 'var' for local variables
tjblasi
2014/07/08 16:36:20
Done.
|
+ |
+ // Indices associated with file urls that will be part of the source map. We |
+ // use a linked hash-map so that `_urls.keys[_urls[u]] == u` |
+ Map<String, int> urls = new LinkedHashMap<String, int>(); |
Siggi Cherem (dart-lang)
2014/07/08 00:31:00
same here and below (var urls = ...)
tjblasi
2014/07/08 16:36:20
Done.
|
+ |
+ // Indices associated with identifiers that will be part of the source map. |
+ // We use a linked hash-map so that `_names.keys[_names[n]] == n` |
+ Map<String, int> names = new LinkedHashMap<String, int>(); |
+ |
+ // The encoding needs to be sorted by the target offsets. |
+ sourceEntries.sort(); |
Siggi Cherem (dart-lang)
2014/07/08 00:31:00
since sorting modifies the list in-place, we might
tjblasi
2014/07/08 16:36:20
Done.
|
+ for (var sourceEntry in sourceEntries) { |
+ if (lines.isEmpty || sourceEntry.target.line > lines.last.line) { |
+ lines.add(new TargetLineEntry(sourceEntry.target.line, [])); |
+ } |
+ |
+ if (sourceEntry.source == null) { |
+ lines.last.entries.add(new TargetEntry(sourceEntry.target.column)); |
Siggi Cherem (dart-lang)
2014/07/08 00:31:01
since `lines.last` can be expensive, maybe we coul
tjblasi
2014/07/08 16:36:20
Done.
|
+ } else { |
+ var urlId = urls.putIfAbsent(sourceEntry.source.sourceUrl, () => urls.length); |
Siggi Cherem (dart-lang)
2014/07/08 00:31:00
nit: 80 columns (here and elsewhere)
tjblasi
2014/07/08 16:36:20
Done.
|
+ var srcNameId = sourceEntry.identifierName != null ? |
Siggi Cherem (dart-lang)
2014/07/08 00:31:01
minor nit: maybe swapping this branch might make i
tjblasi
2014/07/08 16:36:20
Done.
|
+ names.putIfAbsent(sourceEntry.identifierName, () => names.length) : null; |
+ lines.last.entries.add(new TargetEntry( |
+ sourceEntry.target.column, |
+ urlId, |
+ sourceEntry.source.line, |
+ sourceEntry.source.column, |
+ srcNameId)); |
+ } |
+ } |
+ var mapping = new SingleMapping._internal(fileUrl, urls.keys.toList(), names.keys.toList()); |
+ mapping.lines.addAll(lines); |
Siggi Cherem (dart-lang)
2014/07/08 00:31:01
nit: maybe move the default initialization above t
tjblasi
2014/07/08 16:36:20
Done.
|
+ return mapping; |
+ } |
+ |
SingleMapping.fromJson(Map map) |
: targetUrl = map['file'], |
// TODO(sigmund): add support for 'sourceRoot' |
@@ -215,6 +257,66 @@ class SingleMapping extends Mapping { |
} |
} |
+ /// Encodes the Mapping mappings as a json map. |
+ Map toMap() { |
Siggi Cherem (dart-lang)
2014/07/08 00:31:00
suggestion: maybe rename as toJson (to make it con
tjblasi
2014/07/08 16:36:20
Done.
|
+ var buff = new StringBuffer(); |
+ var line = 0; |
+ var column = 0; |
+ var srcLine = 0; |
+ var srcColumn = 0; |
+ var srcUrlId = 0; |
+ var srcNameId = 0; |
+ var first = true; |
+ |
+ for (var entry in lines) { |
+ int nextLine = entry.line; |
+ if (nextLine > line) { |
+ for (int i = line; i < nextLine; ++i) { |
+ buff.write(';'); |
+ } |
+ line = nextLine; |
+ column = 0; |
+ first = true; |
+ } |
+ |
+ for (var segment in entry.entries) { |
+ if (!first) buff.write(','); |
+ first = false; |
+ column = _append(buff, column, segment.column); |
+ |
+ // Encoding can be just the column offset if there is no source |
+ // information. |
+ var newUrlId = segment.sourceUrlId; |
+ if (newUrlId == null) continue; |
+ srcUrlId = _append(buff, srcUrlId, newUrlId); |
+ srcLine = _append(buff, srcLine, segment.sourceLine); |
+ srcColumn = _append(buff, srcColumn, segment.sourceColumn); |
+ |
+ if (segment.sourceNameId == null) continue; |
+ srcNameId = _append(buff, srcNameId, segment.sourceNameId); |
+ } |
+ } |
+ |
+ var result = { |
+ 'version': 3, |
+ 'sourceRoot': '', |
+ 'sources': urls, |
+ 'names' : names, |
+ 'mappings' : buff.toString() |
+ }; |
+ if (targetUrl != null) { |
+ result['file'] = targetUrl; |
+ } |
+ return result; |
+ } |
+ |
+ /// Appends to [buff] a VLQ encoding of [newValue] using the difference |
+ /// between [oldValue] and [newValue] |
+ static int _append(StringBuffer buff, int oldValue, int newValue) { |
+ buff.writeAll(encodeVlq(newValue - oldValue)); |
+ return newValue; |
+ } |
+ |
_segmentError(int seen, int line) => new StateError( |
'Invalid entry in sourcemap, expected 1, 4, or 5' |
' values, but got $seen.\ntargeturl: $targetUrl, line: $line'); |