Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 library dart2js.source_map_builder; | 5 library dart2js.source_map_builder; |
| 6 | 6 |
| 7 import '../util/util.dart'; | 7 import '../util/util.dart'; |
| 8 import '../util/uri_extras.dart' show relativize; | 8 import '../util/uri_extras.dart' show relativize; |
| 9 import 'line_column_provider.dart'; | 9 import 'line_column_provider.dart'; |
| 10 import 'source_information.dart' show SourceFileLocation; | 10 import 'source_information.dart' show SourceLocation; |
| 11 | 11 |
| 12 class SourceMapBuilder { | 12 class SourceMapBuilder { |
| 13 static const int VLQ_BASE_SHIFT = 5; | 13 static const int VLQ_BASE_SHIFT = 5; |
| 14 static const int VLQ_BASE_MASK = (1 << 5) - 1; | 14 static const int VLQ_BASE_MASK = (1 << 5) - 1; |
| 15 static const int VLQ_CONTINUATION_BIT = 1 << 5; | 15 static const int VLQ_CONTINUATION_BIT = 1 << 5; |
| 16 static const int VLQ_CONTINUATION_MASK = 1 << 5; | 16 static const int VLQ_CONTINUATION_MASK = 1 << 5; |
| 17 static const String BASE64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn' | 17 static const String BASE64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn' |
| 18 'opqrstuvwxyz0123456789+/'; | 18 'opqrstuvwxyz0123456789+/'; |
| 19 | 19 |
| 20 final Uri uri; | 20 /// The URI of the source map file. |
| 21 final Uri fileUri; | 21 final Uri sourceMapUri; |
| 22 /// The URI of the target language file. | |
| 23 final Uri targetFileUri; | |
| 22 | 24 |
| 23 LineColumnProvider lineColumnProvider; | 25 LineColumnProvider lineColumnProvider; |
| 24 List<SourceMapEntry> entries; | 26 List<SourceMapEntry> entries; |
| 25 | 27 |
| 26 Map<String, int> sourceUrlMap; | 28 Map<Uri, int> sourceUriMap; |
| 27 List<String> sourceUrlList; | 29 List<Uri> sourceUriList; |
| 28 Map<String, int> sourceNameMap; | 30 Map<String, int> sourceNameMap; |
| 29 List<String> sourceNameList; | 31 List<String> sourceNameList; |
| 30 | 32 |
| 31 int previousTargetLine; | 33 int previousTargetLine; |
| 32 int previousTargetColumn; | 34 int previousTargetColumn; |
| 33 int previousSourceUrlIndex; | 35 int previousSourceUriIndex; |
| 34 int previousSourceLine; | 36 int previousSourceLine; |
| 35 int previousSourceColumn; | 37 int previousSourceColumn; |
| 36 int previousSourceNameIndex; | 38 int previousSourceNameIndex; |
| 37 bool firstEntryInLine; | 39 bool firstEntryInLine; |
| 38 | 40 |
| 39 SourceMapBuilder(this.uri, this.fileUri, this.lineColumnProvider) { | 41 SourceMapBuilder(this.sourceMapUri, |
| 42 this.targetFileUri, | |
| 43 this.lineColumnProvider) { | |
| 40 entries = new List<SourceMapEntry>(); | 44 entries = new List<SourceMapEntry>(); |
| 41 | 45 |
| 42 sourceUrlMap = new Map<String, int>(); | 46 sourceUriMap = new Map<Uri, int>(); |
| 43 sourceUrlList = new List<String>(); | 47 sourceUriList = new List<Uri>(); |
| 44 sourceNameMap = new Map<String, int>(); | 48 sourceNameMap = new Map<String, int>(); |
| 45 sourceNameList = new List<String>(); | 49 sourceNameList = new List<String>(); |
| 46 | 50 |
| 47 previousTargetLine = 0; | 51 previousTargetLine = 0; |
| 48 previousTargetColumn = 0; | 52 previousTargetColumn = 0; |
| 49 previousSourceUrlIndex = 0; | 53 previousSourceUriIndex = 0; |
| 50 previousSourceLine = 0; | 54 previousSourceLine = 0; |
| 51 previousSourceColumn = 0; | 55 previousSourceColumn = 0; |
| 52 previousSourceNameIndex = 0; | 56 previousSourceNameIndex = 0; |
| 53 firstEntryInLine = true; | 57 firstEntryInLine = true; |
| 54 } | 58 } |
| 55 | 59 |
| 56 resetPreviousSourceLocation() { | 60 resetPreviousSourceLocation() { |
| 57 previousSourceUrlIndex = 0; | 61 previousSourceUriIndex = 0; |
| 58 previousSourceLine = 0; | 62 previousSourceLine = 0; |
| 59 previousSourceColumn = 0; | 63 previousSourceColumn = 0; |
| 60 previousSourceNameIndex = 0; | 64 previousSourceNameIndex = 0; |
| 61 } | 65 } |
| 62 | 66 |
| 63 updatePreviousSourceLocation(SourceFileLocation sourceLocation) { | 67 updatePreviousSourceLocation(SourceLocation sourceLocation) { |
| 64 previousSourceLine = sourceLocation.getLine(); | 68 previousSourceLine = sourceLocation.line; |
| 65 previousSourceColumn = sourceLocation.getColumn(); | 69 previousSourceColumn = sourceLocation.column; |
| 66 String sourceUrl = sourceLocation.getSourceUrl(); | 70 Uri sourceUri = sourceLocation.sourceUri; |
| 67 previousSourceUrlIndex = indexOf(sourceUrlList, sourceUrl, sourceUrlMap); | 71 previousSourceUriIndex = indexOf(sourceUriList, sourceUri, sourceUriMap); |
| 68 String sourceName = sourceLocation.getSourceName(); | 72 String sourceName = sourceLocation.sourceName; |
| 69 if (sourceName != null) { | 73 if (sourceName != null) { |
| 70 previousSourceNameIndex = | 74 previousSourceNameIndex = |
| 71 indexOf(sourceNameList, sourceName, sourceNameMap); | 75 indexOf(sourceNameList, sourceName, sourceNameMap); |
| 72 } | 76 } |
| 73 } | 77 } |
| 74 | 78 |
| 75 bool sameAsPreviousLocation(SourceFileLocation sourceLocation) { | 79 bool sameAsPreviousLocation(SourceLocation sourceLocation) { |
| 76 if (sourceLocation == null) { | 80 if (sourceLocation == null) { |
| 77 return true; | 81 return true; |
| 78 } | 82 } |
| 79 int sourceUrlIndex = | 83 int sourceUriIndex = |
| 80 indexOf(sourceUrlList, sourceLocation.getSourceUrl(), sourceUrlMap); | 84 indexOf(sourceUriList, sourceLocation.sourceUri, sourceUriMap); |
| 81 return | 85 return |
| 82 sourceUrlIndex == previousSourceUrlIndex && | 86 sourceUriIndex == previousSourceUriIndex && |
| 83 sourceLocation.getLine() == previousSourceLine && | 87 sourceLocation.line == previousSourceLine && |
| 84 sourceLocation.getColumn() == previousSourceColumn; | 88 sourceLocation.column == previousSourceColumn; |
| 85 } | 89 } |
| 86 | 90 |
| 87 void addMapping(int targetOffset, SourceFileLocation sourceLocation) { | 91 void addMapping(int targetOffset, SourceLocation sourceLocation) { |
| 88 | 92 |
| 89 bool sameLine(int position, otherPosition) { | 93 bool sameLine(int position, otherPosition) { |
| 90 return lineColumnProvider.getLine(position) == | 94 return lineColumnProvider.getLine(position) == |
| 91 lineColumnProvider.getLine(otherPosition); | 95 lineColumnProvider.getLine(otherPosition); |
| 92 } | 96 } |
| 93 | 97 |
| 94 if (!entries.isEmpty && sameLine(targetOffset, entries.last.targetOffset)) { | 98 if (!entries.isEmpty && sameLine(targetOffset, entries.last.targetOffset)) { |
| 95 if (sameAsPreviousLocation(sourceLocation)) { | 99 if (sameAsPreviousLocation(sourceLocation)) { |
| 96 // The entry points to the same source location as the previous entry in | 100 // The entry points to the same source location as the previous entry in |
| 97 // the same line, hence it is not needed for the source map. | 101 // the same line, hence it is not needed for the source map. |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 125 | 129 |
| 126 String build() { | 130 String build() { |
| 127 resetPreviousSourceLocation(); | 131 resetPreviousSourceLocation(); |
| 128 StringBuffer mappingsBuffer = new StringBuffer(); | 132 StringBuffer mappingsBuffer = new StringBuffer(); |
| 129 entries.forEach((SourceMapEntry entry) { | 133 entries.forEach((SourceMapEntry entry) { |
| 130 writeEntry(entry, mappingsBuffer); | 134 writeEntry(entry, mappingsBuffer); |
| 131 }); | 135 }); |
| 132 StringBuffer buffer = new StringBuffer(); | 136 StringBuffer buffer = new StringBuffer(); |
| 133 buffer.write('{\n'); | 137 buffer.write('{\n'); |
| 134 buffer.write(' "version": 3,\n'); | 138 buffer.write(' "version": 3,\n'); |
| 135 if (uri != null && fileUri != null) { | 139 if (sourceMapUri != null && targetFileUri != null) { |
| 136 buffer.write(' "file": "${relativize(uri, fileUri, false)}",\n'); | 140 buffer.write( |
| 141 ' "file": "${relativize(sourceMapUri, targetFileUri, false)}",\n'); | |
| 137 } | 142 } |
| 138 buffer.write(' "sourceRoot": "",\n'); | 143 buffer.write(' "sourceRoot": "",\n'); |
| 139 buffer.write(' "sources": '); | 144 buffer.write(' "sources": '); |
| 140 if (uri != null) { | 145 List<String> relativeSourceUriList = <String>[]; |
| 141 sourceUrlList = | 146 if (sourceMapUri != null) { |
| 142 sourceUrlList.map((url) => relativize(uri, Uri.parse(url), false)) | 147 relativeSourceUriList = |
|
floitsch
2015/02/13 13:46:03
maybe:
relativeSourceUriList = sourceUriList
.
Johnni Winther
2015/02/13 13:55:49
Done.
| |
| 148 sourceUriList.map((u) => relativize(sourceMapUri, u, false)) | |
| 143 .toList(); | 149 .toList(); |
| 144 } | 150 } |
| 145 printStringListOn(sourceUrlList, buffer); | 151 printStringListOn(relativeSourceUriList, buffer); |
| 146 buffer.write(',\n'); | 152 buffer.write(',\n'); |
| 147 buffer.write(' "names": '); | 153 buffer.write(' "names": '); |
| 148 printStringListOn(sourceNameList, buffer); | 154 printStringListOn(sourceNameList, buffer); |
| 149 buffer.write(',\n'); | 155 buffer.write(',\n'); |
| 150 buffer.write(' "mappings": "'); | 156 buffer.write(' "mappings": "'); |
| 151 buffer.write(mappingsBuffer); | 157 buffer.write(mappingsBuffer); |
| 152 buffer.write('"\n}\n'); | 158 buffer.write('"\n}\n'); |
| 153 return buffer.toString(); | 159 return buffer.toString(); |
| 154 } | 160 } |
| 155 | 161 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 170 if (!firstEntryInLine) { | 176 if (!firstEntryInLine) { |
| 171 output.write(','); | 177 output.write(','); |
| 172 } | 178 } |
| 173 firstEntryInLine = false; | 179 firstEntryInLine = false; |
| 174 | 180 |
| 175 encodeVLQ(output, targetColumn - previousTargetColumn); | 181 encodeVLQ(output, targetColumn - previousTargetColumn); |
| 176 previousTargetColumn = targetColumn; | 182 previousTargetColumn = targetColumn; |
| 177 | 183 |
| 178 if (entry.sourceLocation == null) return; | 184 if (entry.sourceLocation == null) return; |
| 179 | 185 |
| 180 String sourceUrl = entry.sourceLocation.getSourceUrl(); | 186 Uri sourceUri = entry.sourceLocation.sourceUri; |
| 181 int sourceLine = entry.sourceLocation.getLine(); | 187 int sourceLine = entry.sourceLocation.line; |
| 182 int sourceColumn = entry.sourceLocation.getColumn(); | 188 int sourceColumn = entry.sourceLocation.column; |
| 183 String sourceName = entry.sourceLocation.getSourceName(); | 189 String sourceName = entry.sourceLocation.sourceName; |
| 184 | 190 |
| 185 int sourceUrlIndex = indexOf(sourceUrlList, sourceUrl, sourceUrlMap); | 191 int sourceUriIndex = indexOf(sourceUriList, sourceUri, sourceUriMap); |
| 186 encodeVLQ(output, sourceUrlIndex - previousSourceUrlIndex); | 192 encodeVLQ(output, sourceUriIndex - previousSourceUriIndex); |
| 187 encodeVLQ(output, sourceLine - previousSourceLine); | 193 encodeVLQ(output, sourceLine - previousSourceLine); |
| 188 encodeVLQ(output, sourceColumn - previousSourceColumn); | 194 encodeVLQ(output, sourceColumn - previousSourceColumn); |
| 189 | 195 |
| 190 if (sourceName != null) { | 196 if (sourceName != null) { |
| 191 int sourceNameIndex = indexOf(sourceNameList, sourceName, sourceNameMap); | 197 int sourceNameIndex = indexOf(sourceNameList, sourceName, sourceNameMap); |
| 192 encodeVLQ(output, sourceNameIndex - previousSourceNameIndex); | 198 encodeVLQ(output, sourceNameIndex - previousSourceNameIndex); |
| 193 } | 199 } |
| 194 | 200 |
| 195 // Update previous source location to ensure the next indices are relative | 201 // Update previous source location to ensure the next indices are relative |
| 196 // to those if [entry.sourceLocation]. | 202 // to those if [entry.sourceLocation]. |
| 197 updatePreviousSourceLocation(entry.sourceLocation); | 203 updatePreviousSourceLocation(entry.sourceLocation); |
| 198 } | 204 } |
| 199 | 205 |
| 200 int indexOf(List<String> list, String value, Map<String, int> map) { | 206 int indexOf(List list, value, Map<dynamic, int> map) { |
| 201 return map.putIfAbsent(value, () { | 207 return map.putIfAbsent(value, () { |
| 202 int index = list.length; | 208 int index = list.length; |
| 203 list.add(value); | 209 list.add(value); |
| 204 return index; | 210 return index; |
| 205 }); | 211 }); |
| 206 } | 212 } |
| 207 | 213 |
| 208 static void encodeVLQ(StringBuffer output, int value) { | 214 static void encodeVLQ(StringBuffer output, int value) { |
| 209 int signBit = 0; | 215 int signBit = 0; |
| 210 if (value < 0) { | 216 if (value < 0) { |
| 211 signBit = 1; | 217 signBit = 1; |
| 212 value = -value; | 218 value = -value; |
| 213 } | 219 } |
| 214 value = (value << 1) | signBit; | 220 value = (value << 1) | signBit; |
| 215 do { | 221 do { |
| 216 int digit = value & VLQ_BASE_MASK; | 222 int digit = value & VLQ_BASE_MASK; |
| 217 value >>= VLQ_BASE_SHIFT; | 223 value >>= VLQ_BASE_SHIFT; |
| 218 if (value > 0) { | 224 if (value > 0) { |
| 219 digit |= VLQ_CONTINUATION_BIT; | 225 digit |= VLQ_CONTINUATION_BIT; |
| 220 } | 226 } |
| 221 output.write(BASE64_DIGITS[digit]); | 227 output.write(BASE64_DIGITS[digit]); |
| 222 } while (value > 0); | 228 } while (value > 0); |
| 223 } | 229 } |
| 224 } | 230 } |
| 225 | 231 |
| 226 class SourceMapEntry { | 232 class SourceMapEntry { |
| 227 SourceFileLocation sourceLocation; | 233 SourceLocation sourceLocation; |
| 228 int targetOffset; | 234 int targetOffset; |
| 229 | 235 |
| 230 SourceMapEntry(this.sourceLocation, this.targetOffset); | 236 SourceMapEntry(this.sourceLocation, this.targetOffset); |
| 231 } | 237 } |
| OLD | NEW |