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 |