Fix bug in source-maps parsing: parser failed when most information could be
inferred. This fixes bug http://dartbug.com/11782
R=dgrove@google.com
Review URL: https://codereview.chromium.org//19019006
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/source_maps@24981 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/lib/builder.dart b/lib/builder.dart
index ad80fa0..be00c9e 100644
--- a/lib/builder.dart
+++ b/lib/builder.dart
@@ -74,12 +74,20 @@
first = false;
column = _append(buff, column, entry.target.column);
- if (entry.source == null) continue;
+ // Encoding can be just the column offset if there is no source
+ // information, or if two consecutive mappings share exactly the same
+ // source information.
+ var source = entry.source;
+ if (source == null) continue;
+ var newUrlId = _indexOf(_urls, source.sourceUrl);
+ if (newUrlId == srcUrlId && source.line == srcLine
+ && source.column == srcColumn && entry.identifierName == null) {
+ continue;
+ }
- srcUrlId = _append(buff, srcUrlId,
- _indexOf(_urls, entry.source.sourceUrl));
- srcLine = _append(buff, srcLine, entry.source.line);
- srcColumn = _append(buff, srcColumn, entry.source.column);
+ srcUrlId = _append(buff, srcUrlId, newUrlId);
+ srcLine = _append(buff, srcLine, source.line);
+ srcColumn = _append(buff, srcColumn, source.column);
if (entry.identifierName == null) continue;
srcNameId = _append(buff, srcNameId,
diff --git a/lib/parser.dart b/lib/parser.dart
index 3849913..e293263 100644
--- a/lib/parser.dart
+++ b/lib/parser.dart
@@ -25,9 +25,8 @@
'Only version 3 is supported.');
}
- // TODO(sigmund): relax this? dart2js doesn't generate the file entry.
if (!map.containsKey('file')) {
- throw new ArgumentError('missing "file" in source map');
+ print('warning: missing "file" entry in source map');
}
if (map.containsKey('sections')) {
@@ -186,7 +185,7 @@
if (tokenizer.nextKind.isNewSegment) throw _segmentError(0, line);
column += tokenizer._consumeValue();
if (!tokenizer.nextKind.isValue) {
- entries.add(new TargetEntry(column));
+ entries.add(new TargetEntry(column, srcUrlId, srcLine, srcColumn));
} else {
srcUrlId += tokenizer._consumeValue();
if (srcUrlId >= urls.length) {
@@ -242,7 +241,6 @@
}
Span spanFor(int line, int column, {Map<String, SourceFile> files}) {
- var lineEntry = _findLine(line);
var entry = _findColumn(line, column, _findLine(line));
if (entry == null) return null;
var url = urls[entry.sourceUrlId];
@@ -323,8 +321,9 @@
final int sourceLine;
final int sourceColumn;
final int sourceNameId;
- TargetEntry(this.column, [this.sourceUrlId, this.sourceLine,
- this.sourceColumn, this.sourceNameId]);
+
+ TargetEntry(this.column, this.sourceUrlId, this.sourceLine,
+ this.sourceColumn, [this.sourceNameId]);
String toString() => '$runtimeType: '
'($column, $sourceUrlId, $sourceLine, $sourceColumn, $sourceNameId)';
diff --git a/lib/source_maps.dart b/lib/source_maps.dart
index 1594827..8fc48c9 100644
--- a/lib/source_maps.dart
+++ b/lib/source_maps.dart
@@ -2,22 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-/// Source maps library.
-///
-/// ## Installing ##
-///
-/// Use [pub][] to install this package. Add the following to your
-/// `pubspec.yaml` file.
-///
-/// dependencies:
-/// source_maps: any
-///
-/// Then run `pub install`.
-///
-/// For more information, see the
-/// [source_maps package on pub.dartlang.org][pkg].
-///
-/// ## Using ##
+/// Library to create and parse source maps.
///
/// Create a source map using [SourceMapBuilder]. For example:
/// var json = (new SourceMapBuilder()
@@ -33,6 +18,20 @@
/// var mapping = parse(json);
/// mapping.spanFor(outputSpan1.line, outputSpan1.column)
///
+/// ## Getting the code ##
+///
+/// This library is distributed as a [pub][] package. To install this package,
+/// add the following to your `pubspec.yaml` file:
+///
+/// dependencies:
+/// source_maps: any
+///
+/// After you run `pub install`, you should be able to access this library by
+/// importing `package:source_maps/source_maps.dart`.
+///
+/// For more information, see the
+/// [source_maps package on pub.dartlang.org][pkg].
+///
/// [pub]: http://pub.dartlang.org
/// [pkg]: http://pub.dartlang.org/packages/source_maps
library source_maps;
diff --git a/pubspec.yaml b/pubspec.yaml
index a559b58..4ae1802 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: source_maps
author: "Dart Team <misc@dartlang.org>"
-homepage: https://github.com/dart-lang/source-maps
+homepage: http://www.dartlang.org
description: Library to programmatically manipulate source map files.
dev_dependencies:
unittest: any
diff --git a/test/common.dart b/test/common.dart
index 661979b..0c1f28a 100644
--- a/test/common.dart
+++ b/test/common.dart
@@ -27,6 +27,11 @@
Span inputVar1 = ispan(30, 38, true);
Span inputFunction = ispan(74, 82, true);
Span inputVar2 = ispan(87, 95, true);
+
+Span inputVar1NoSymbol = ispan(30, 38);
+Span inputFunctionNoSymbol = ispan(74, 82);
+Span inputVar2NoSymbol = ispan(87, 95);
+
Span inputExpr = ispan(108, 127);
/// Content of the target file
@@ -43,6 +48,9 @@
Span outputVar1 = ospan(4, 5, true);
Span outputFunction = ospan(11, 12, true);
Span outputVar2 = ospan(13, 14, true);
+Span outputVar1NoSymbol = ospan(4, 5);
+Span outputFunctionNoSymbol = ospan(11, 12);
+Span outputVar2NoSymbol = ospan(13, 14);
Span outputExpr = ospan(19, 24);
/// Expected output mapping when recording the following four mappings:
diff --git a/test/end2end_test.dart b/test/end2end_test.dart
index 5ea958a..99fe40d 100644
--- a/test/end2end_test.dart
+++ b/test/end2end_test.dart
@@ -13,11 +13,17 @@
expect(inputVar1.text, 'longVar1');
expect(inputFunction.text, 'longName');
expect(inputVar2.text, 'longVar2');
+ expect(inputVar1NoSymbol.text, 'longVar1');
+ expect(inputFunctionNoSymbol.text, 'longName');
+ expect(inputVar2NoSymbol.text, 'longVar2');
expect(inputExpr.text, 'longVar1 + longVar2');
expect(outputVar1.text, 'x');
expect(outputFunction.text, 'f');
expect(outputVar2.text, 'y');
+ expect(outputVar1NoSymbol.text, 'x');
+ expect(outputFunctionNoSymbol.text, 'f');
+ expect(outputVar2NoSymbol.text, 'y');
expect(outputExpr.text, 'x + y');
});
@@ -35,6 +41,55 @@
check(outputExpr, mapping, inputExpr, false);
});
+ test('build + parse - no symbols', () {
+ var map = (new SourceMapBuilder()
+ ..addSpan(inputVar1NoSymbol, outputVar1NoSymbol)
+ ..addSpan(inputFunctionNoSymbol, outputFunctionNoSymbol)
+ ..addSpan(inputVar2NoSymbol, outputVar2NoSymbol)
+ ..addSpan(inputExpr, outputExpr))
+ .build(output.url);
+ var mapping = parseJson(map);
+ check(outputVar1NoSymbol, mapping, inputVar1NoSymbol, false);
+ check(outputVar2NoSymbol, mapping, inputVar2NoSymbol, false);
+ check(outputFunctionNoSymbol, mapping, inputFunctionNoSymbol, false);
+ check(outputExpr, mapping, inputExpr, false);
+ });
+
+ test('build + parse, repeated entries', () {
+ var map = (new SourceMapBuilder()
+ ..addSpan(inputVar1, outputVar1)
+ ..addSpan(inputVar1, outputVar1)
+ ..addSpan(inputFunction, outputFunction)
+ ..addSpan(inputFunction, outputFunction)
+ ..addSpan(inputVar2, outputVar2)
+ ..addSpan(inputVar2, outputVar2)
+ ..addSpan(inputExpr, outputExpr)
+ ..addSpan(inputExpr, outputExpr))
+ .build(output.url);
+ var mapping = parseJson(map);
+ check(outputVar1, mapping, inputVar1, false);
+ check(outputVar2, mapping, inputVar2, false);
+ check(outputFunction, mapping, inputFunction, false);
+ check(outputExpr, mapping, inputExpr, false);
+ });
+
+ test('build + parse - no symbols, repeated entries', () {
+ var map = (new SourceMapBuilder()
+ ..addSpan(inputVar1NoSymbol, outputVar1NoSymbol)
+ ..addSpan(inputVar1NoSymbol, outputVar1NoSymbol)
+ ..addSpan(inputFunctionNoSymbol, outputFunctionNoSymbol)
+ ..addSpan(inputFunctionNoSymbol, outputFunctionNoSymbol)
+ ..addSpan(inputVar2NoSymbol, outputVar2NoSymbol)
+ ..addSpan(inputVar2NoSymbol, outputVar2NoSymbol)
+ ..addSpan(inputExpr, outputExpr))
+ .build(output.url);
+ var mapping = parseJson(map);
+ check(outputVar1NoSymbol, mapping, inputVar1NoSymbol, false);
+ check(outputVar2NoSymbol, mapping, inputVar2NoSymbol, false);
+ check(outputFunctionNoSymbol, mapping, inputFunctionNoSymbol, false);
+ check(outputExpr, mapping, inputExpr, false);
+ });
+
test('build + parse with file', () {
var json = (new SourceMapBuilder()
..addSpan(inputVar1, outputVar1)