Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(284)

Side by Side Diff: pkg/source_maps/lib/parser.dart

Issue 19019006: Fix bug in source-maps parsing: parser failed when most information could be (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /// Contains the top-level function to parse source maps version 3. 5 /// Contains the top-level function to parse source maps version 3.
6 library source_maps.parser; 6 library source_maps.parser;
7 7
8 import 'dart:json' as json; 8 import 'dart:json' as json;
9 9
10 import 'span.dart'; 10 import 'span.dart';
11 import 'src/utils.dart'; 11 import 'src/utils.dart';
12 import 'src/vlq.dart'; 12 import 'src/vlq.dart';
13 13
14 /// Parses a source map directly from a json string. 14 /// Parses a source map directly from a json string.
15 // TODO(sigmund): evaluate whether other maps should have the json parsed, or 15 // TODO(sigmund): evaluate whether other maps should have the json parsed, or
16 // the string represenation. 16 // the string represenation.
17 Mapping parse(String jsonMap, {Map<String, Map> otherMaps}) => 17 Mapping parse(String jsonMap, {Map<String, Map> otherMaps}) =>
18 parseJson(json.parse(jsonMap), otherMaps: otherMaps); 18 parseJson(json.parse(jsonMap), otherMaps: otherMaps);
19 19
20 /// Parses a source map directly from a json map object. 20 /// Parses a source map directly from a json map object.
21 Mapping parseJson(Map map, {Map<String, Map> otherMaps}) { 21 Mapping parseJson(Map map, {Map<String, Map> otherMaps}) {
22 if (map['version'] != 3) { 22 if (map['version'] != 3) {
23 throw new ArgumentError( 23 throw new ArgumentError(
24 'unexpected source map version: ${map["version"]}. ' 24 'unexpected source map version: ${map["version"]}. '
25 'Only version 3 is supported.'); 25 'Only version 3 is supported.');
26 } 26 }
27 27
28 // TODO(sigmund): relax this? dart2js doesn't generate the file entry.
29 if (!map.containsKey('file')) { 28 if (!map.containsKey('file')) {
30 throw new ArgumentError('missing "file" in source map'); 29 print('warning: missing "file" entry in source map');
31 } 30 }
32 31
33 if (map.containsKey('sections')) { 32 if (map.containsKey('sections')) {
34 if (map.containsKey('mappings') || map.containsKey('sources') || 33 if (map.containsKey('mappings') || map.containsKey('sources') ||
35 map.containsKey('names')) { 34 map.containsKey('names')) {
36 throw new FormatException('map containing "sections" ' 35 throw new FormatException('map containing "sections" '
37 'cannot contain "mappings", "sources", or "names".'); 36 'cannot contain "mappings", "sources", or "names".');
38 } 37 }
39 return new MultiSectionMapping.fromJson(map['sections'], otherMaps); 38 return new MultiSectionMapping.fromJson(map['sections'], otherMaps);
40 } 39 }
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 // following order: 178 // following order:
180 // 0: the starting column in the current line of the generated file 179 // 0: the starting column in the current line of the generated file
181 // 1: the id of the original source file 180 // 1: the id of the original source file
182 // 2: the starting line in the original source 181 // 2: the starting line in the original source
183 // 3: the starting column in the original source 182 // 3: the starting column in the original source
184 // 4: the id of the original symbol name 183 // 4: the id of the original symbol name
185 // The values are relative to the previous encountered values. 184 // The values are relative to the previous encountered values.
186 if (tokenizer.nextKind.isNewSegment) throw _segmentError(0, line); 185 if (tokenizer.nextKind.isNewSegment) throw _segmentError(0, line);
187 column += tokenizer._consumeValue(); 186 column += tokenizer._consumeValue();
188 if (!tokenizer.nextKind.isValue) { 187 if (!tokenizer.nextKind.isValue) {
189 entries.add(new TargetEntry(column)); 188 entries.add(new TargetEntry(column, srcUrlId, srcLine, srcColumn));
190 } else { 189 } else {
191 srcUrlId += tokenizer._consumeValue(); 190 srcUrlId += tokenizer._consumeValue();
192 if (srcUrlId >= urls.length) { 191 if (srcUrlId >= urls.length) {
193 throw new StateError( 192 throw new StateError(
194 'Invalid source url id. $targetUrl, $line, $srcUrlId'); 193 'Invalid source url id. $targetUrl, $line, $srcUrlId');
195 } 194 }
196 if (!tokenizer.nextKind.isValue) throw _segmentError(2, line); 195 if (!tokenizer.nextKind.isValue) throw _segmentError(2, line);
197 srcLine += tokenizer._consumeValue(); 196 srcLine += tokenizer._consumeValue();
198 if (!tokenizer.nextKind.isValue) throw _segmentError(3, line); 197 if (!tokenizer.nextKind.isValue) throw _segmentError(3, line);
199 srcColumn += tokenizer._consumeValue(); 198 srcColumn += tokenizer._consumeValue();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 /// the very last entry on that line. 234 /// the very last entry on that line.
236 TargetEntry _findColumn(int line, int column, TargetLineEntry lineEntry) { 235 TargetEntry _findColumn(int line, int column, TargetLineEntry lineEntry) {
237 if (lineEntry == null || lineEntry.entries.length == 0) return null; 236 if (lineEntry == null || lineEntry.entries.length == 0) return null;
238 if (lineEntry.line != line) return lineEntry.entries.last; 237 if (lineEntry.line != line) return lineEntry.entries.last;
239 var entries = lineEntry.entries; 238 var entries = lineEntry.entries;
240 int index = binarySearch(entries, (e) => e.column > column); 239 int index = binarySearch(entries, (e) => e.column > column);
241 return (index <= 0) ? null : entries[index - 1]; 240 return (index <= 0) ? null : entries[index - 1];
242 } 241 }
243 242
244 Span spanFor(int line, int column, {Map<String, SourceFile> files}) { 243 Span spanFor(int line, int column, {Map<String, SourceFile> files}) {
245 var lineEntry = _findLine(line);
246 var entry = _findColumn(line, column, _findLine(line)); 244 var entry = _findColumn(line, column, _findLine(line));
247 if (entry == null) return null; 245 if (entry == null) return null;
248 var url = urls[entry.sourceUrlId]; 246 var url = urls[entry.sourceUrlId];
249 if (files != null && files[url] != null) { 247 if (files != null && files[url] != null) {
250 var file = files[url]; 248 var file = files[url];
251 var start = file.getOffset(entry.sourceLine, entry.sourceColumn); 249 var start = file.getOffset(entry.sourceLine, entry.sourceColumn);
252 if (entry.sourceNameId != null) { 250 if (entry.sourceNameId != null) {
253 var text = names[entry.sourceNameId]; 251 var text = names[entry.sourceNameId];
254 return new FileSpan(files[url], start, start + text.length, true); 252 return new FileSpan(files[url], start, start + text.length, true);
255 } else { 253 } else {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 String toString() => '$runtimeType: $line $entries'; 314 String toString() => '$runtimeType: $line $entries';
317 } 315 }
318 316
319 /// A target segment entry read from a source map 317 /// A target segment entry read from a source map
320 class TargetEntry { 318 class TargetEntry {
321 final int column; 319 final int column;
322 final int sourceUrlId; 320 final int sourceUrlId;
323 final int sourceLine; 321 final int sourceLine;
324 final int sourceColumn; 322 final int sourceColumn;
325 final int sourceNameId; 323 final int sourceNameId;
326 TargetEntry(this.column, [this.sourceUrlId, this.sourceLine, 324
327 this.sourceColumn, this.sourceNameId]); 325 TargetEntry(this.column, this.sourceUrlId, this.sourceLine,
326 this.sourceColumn, [this.sourceNameId]);
328 327
329 String toString() => '$runtimeType: ' 328 String toString() => '$runtimeType: '
330 '($column, $sourceUrlId, $sourceLine, $sourceColumn, $sourceNameId)'; 329 '($column, $sourceUrlId, $sourceLine, $sourceColumn, $sourceNameId)';
331 } 330 }
332 331
333 /** A character iterator over a string that can peek one character ahead. */ 332 /** A character iterator over a string that can peek one character ahead. */
334 class _MappingTokenizer implements Iterator<String> { 333 class _MappingTokenizer implements Iterator<String> {
335 final String _internal; 334 final String _internal;
336 final int _length; 335 final int _length;
337 int index = -1; 336 int index = -1;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 static const _TokenKind EOF = const _TokenKind(isEof: true); 381 static const _TokenKind EOF = const _TokenKind(isEof: true);
383 static const _TokenKind VALUE = const _TokenKind(); 382 static const _TokenKind VALUE = const _TokenKind();
384 final bool isNewLine; 383 final bool isNewLine;
385 final bool isNewSegment; 384 final bool isNewSegment;
386 final bool isEof; 385 final bool isEof;
387 bool get isValue => !isNewLine && !isNewSegment && !isEof; 386 bool get isValue => !isNewLine && !isNewSegment && !isEof;
388 387
389 const _TokenKind( 388 const _TokenKind(
390 {this.isNewLine: false, this.isNewSegment: false, this.isEof: false}); 389 {this.isNewLine: false, this.isNewSegment: false, this.isEof: false});
391 } 390 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698