Chromium Code Reviews| Index: lib/compiler/implementation/util/source_map_builder.dart |
| diff --git a/lib/compiler/implementation/util/source_map_builder.dart b/lib/compiler/implementation/util/source_map_builder.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..87f9f19e0821456231e6f4e23bc3ccc8a64d5831 |
| --- /dev/null |
| +++ b/lib/compiler/implementation/util/source_map_builder.dart |
| @@ -0,0 +1,139 @@ |
| +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| +// 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. |
| + |
| +#library('source_map_builder'); |
| + |
| +#import('dart:json'); |
| + |
| +#import('../source_file.dart'); |
| + |
| +class SourceMappingEntry { |
| + SourceFile sourceFile; |
| + int sourceOffset; |
| + int targetOffset; |
| + String sourceName; |
| + |
| + SourceMappingEntry(this.sourceFile, this.sourceOffset, this.targetOffset, [this.sourceName]); |
|
ahe
2012/06/19 17:00:41
Lines should be limited to 80 columns.
podivilov
2012/06/20 09:37:14
Done.
|
| +} |
| + |
| +class SourceMapBuilder { |
| + static final int VLQ_BASE_SHIFT = 5; |
| + static final int VLQ_BASE_MASK = (1 << 5) - 1; |
| + static final int VLQ_CONTINUATION_BIT = 1 << 5; |
| + static final int VLQ_CONTINUATION_MASK = 1 << 5; |
| + static final String BASE64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; |
| + |
| + Map<String, int> sourceURLMap; |
| + List<String> sourceURLList; |
| + Map<String, int> sourceNameMap; |
| + List<String> sourceNameList; |
| + |
| + int previousTargetLine; |
| + int previousTargetColumn; |
| + int previousSourceURLIndex; |
| + int previousSourceLine; |
| + int previousSourceColumn; |
| + int previousSourceNameIndex; |
| + bool firstEntryInLine; |
| + |
| + SourceMapBuilder() { |
| + sourceURLMap = new Map<String, int>(); |
| + sourceURLList = new List<String>(); |
| + sourceNameMap = new Map<String, int>(); |
| + sourceNameList = new List<String>(); |
| + |
| + previousTargetLine = 0; |
| + previousTargetColumn = 0; |
| + previousSourceURLIndex = 0; |
| + previousSourceLine = 0; |
| + previousSourceColumn = 0; |
| + previousSourceNameIndex = 0; |
| + firstEntryInLine = true; |
| + } |
| + |
| + String build(List<SourceMappingEntry> mappingEntries, SourceFile targetFile) { |
| + StringBuffer mappingsBuffer = new StringBuffer(); |
| + mappingEntries.forEach((SourceMappingEntry entry) { |
| + writeEntry(entry, targetFile, mappingsBuffer); |
| + }); |
| + |
| + Map<String, Object> sourceMap = new Map<String, Object>(); |
| + sourceMap['version'] = 3; |
| + sourceMap['mappings'] = mappingsBuffer.toString(); |
| + sourceMap['sources'] = sourceURLList; |
| + sourceMap['names'] = sourceNameList; |
| + return JSON.stringify(sourceMap); |
|
ahe
2012/06/19 17:00:41
Seriously?
|
| + } |
| + |
| + void writeEntry(SourceMappingEntry entry, SourceFile targetFile, StringBuffer output) { |
| + int targetLine = targetFile.getLine(entry.targetOffset); |
| + int targetColumn = targetFile.getColumn(targetLine, entry.targetOffset); |
| + String sourceURL = entry.sourceFile.filename; |
| + int sourceLine = entry.sourceFile.getLine(entry.sourceOffset); |
| + int sourceColumn = entry.sourceFile.getColumn(sourceLine, entry.sourceOffset); |
| + String sourceName = entry.sourceName; |
| + |
| + if (targetLine > previousTargetLine) { |
| + for (int i = previousTargetLine; i < targetLine; ++i) { |
| + output.add(';'); |
| + } |
| + previousTargetLine = targetLine; |
| + previousTargetColumn = 0; |
| + firstEntryInLine = true; |
| + } |
| + |
| + if (!firstEntryInLine) { |
| + output.add(','); |
| + } |
| + firstEntryInLine = false; |
| + |
| + encodeVLQ(output, targetColumn - previousTargetColumn); |
| + previousTargetColumn = targetColumn; |
| + |
| + if (sourceURL === null) |
| + return; |
| + |
| + int sourceURLIndex = indexOf(sourceURLList, sourceURL, sourceURLMap); |
| + encodeVLQ(output, sourceURLIndex - previousSourceURLIndex); |
| + previousSourceURLIndex = sourceURLIndex; |
| + |
| + encodeVLQ(output, sourceLine - previousSourceLine); |
| + previousSourceLine = sourceLine; |
| + encodeVLQ(output, sourceColumn - previousSourceColumn); |
| + previousSourceColumn = sourceColumn; |
| + |
| + if (sourceName === null) |
| + return; |
| + |
| + int sourceNameIndex = indexOf(sourceNameList, sourceName, sourceNameMap); |
| + encodeVLQ(output, sourceNameIndex - previousSourceNameIndex); |
| + previousSourceNameIndex = sourceNameIndex; |
| + } |
| + |
| + int indexOf(List<String> list, String value, Map<String, int> map) { |
| + return map.putIfAbsent(value, () { |
| + int index = list.length; |
| + map[value] = index; |
| + list.add(value); |
| + return index; |
| + }); |
| + } |
| + |
| + static void encodeVLQ(StringBuffer output, int value) { |
| + int signBit = 0; |
| + if (value < 0) { |
| + signBit = 1; |
| + value = -value; |
| + } |
| + value = (value << 1) | signBit; |
| + do { |
| + int digit = value & VLQ_BASE_MASK; |
| + value >>= VLQ_BASE_SHIFT; |
| + if (value > 0) { |
| + digit |= VLQ_CONTINUATION_BIT; |
| + } |
| + output.add(BASE64_DIGITS[digit]); |
| + } while (value > 0); |
| + } |
| +} |