| 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('source_map_builder'); | 5 #library('source_map_builder'); |
| 6 | 6 |
| 7 #import('dart:json'); | 7 #import('dart:json'); |
| 8 | 8 |
| 9 #import('scanner/scannerlib.dart'); |
| 9 #import('source_file.dart'); | 10 #import('source_file.dart'); |
| 10 | 11 |
| 11 class SourceMapBuilder { | 12 class SourceMapBuilder { |
| 12 static const int VLQ_BASE_SHIFT = 5; | 13 static const int VLQ_BASE_SHIFT = 5; |
| 13 static const int VLQ_BASE_MASK = (1 << 5) - 1; | 14 static const int VLQ_BASE_MASK = (1 << 5) - 1; |
| 14 static const int VLQ_CONTINUATION_BIT = 1 << 5; | 15 static const int VLQ_CONTINUATION_BIT = 1 << 5; |
| 15 static const int VLQ_CONTINUATION_MASK = 1 << 5; | 16 static const int VLQ_CONTINUATION_MASK = 1 << 5; |
| 16 static const String BASE64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn' | 17 static const String BASE64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn' |
| 17 'opqrstuvwxyz0123456789+/'; | 18 'opqrstuvwxyz0123456789+/'; |
| 18 | 19 |
| 19 List<_Entry> entries; | 20 List<SourceMapEntry> entries; |
| 20 | 21 |
| 21 Map<String, int> sourceUrlMap; | 22 Map<String, int> sourceUrlMap; |
| 22 List<String> sourceUrlList; | 23 List<String> sourceUrlList; |
| 23 Map<String, int> sourceNameMap; | 24 Map<String, int> sourceNameMap; |
| 24 List<String> sourceNameList; | 25 List<String> sourceNameList; |
| 25 | 26 |
| 26 int previousTargetLine; | 27 int previousTargetLine; |
| 27 int previousTargetColumn; | 28 int previousTargetColumn; |
| 28 int previousSourceUrlIndex; | 29 int previousSourceUrlIndex; |
| 29 int previousSourceLine; | 30 int previousSourceLine; |
| 30 int previousSourceColumn; | 31 int previousSourceColumn; |
| 31 int previousSourceNameIndex; | 32 int previousSourceNameIndex; |
| 32 bool firstEntryInLine; | 33 bool firstEntryInLine; |
| 33 | 34 |
| 34 SourceMapBuilder() { | 35 SourceMapBuilder() { |
| 35 entries = new List<_Entry>(); | 36 entries = new List<SourceMapEntry>(); |
| 36 | 37 |
| 37 sourceUrlMap = new Map<String, int>(); | 38 sourceUrlMap = new Map<String, int>(); |
| 38 sourceUrlList = new List<String>(); | 39 sourceUrlList = new List<String>(); |
| 39 sourceNameMap = new Map<String, int>(); | 40 sourceNameMap = new Map<String, int>(); |
| 40 sourceNameList = new List<String>(); | 41 sourceNameList = new List<String>(); |
| 41 | 42 |
| 42 previousTargetLine = 0; | 43 previousTargetLine = 0; |
| 43 previousTargetColumn = 0; | 44 previousTargetColumn = 0; |
| 44 previousSourceUrlIndex = 0; | 45 previousSourceUrlIndex = 0; |
| 45 previousSourceLine = 0; | 46 previousSourceLine = 0; |
| 46 previousSourceColumn = 0; | 47 previousSourceColumn = 0; |
| 47 previousSourceNameIndex = 0; | 48 previousSourceNameIndex = 0; |
| 48 firstEntryInLine = true; | 49 firstEntryInLine = true; |
| 49 } | 50 } |
| 50 | 51 |
| 51 void addMapping(SourceFile sourceFile, int sourceOffset, String sourceName, | 52 void addMapping(int targetOffset, SourceFileLocation sourceLocation) { |
| 52 int targetOffset) { | 53 entries.add(new SourceMapEntry(sourceLocation, targetOffset)); |
| 53 entries.add(new _Entry(sourceFile, sourceOffset, sourceName, targetOffset)); | |
| 54 } | 54 } |
| 55 | 55 |
| 56 String build(SourceFile targetFile) { | 56 String build(SourceFile targetFile) { |
| 57 StringBuffer buffer = new StringBuffer(); | 57 StringBuffer buffer = new StringBuffer(); |
| 58 buffer.add('{\n'); | 58 buffer.add('{\n'); |
| 59 buffer.add(' "version": 3,\n'); | 59 buffer.add(' "version": 3,\n'); |
| 60 buffer.add(' "mappings": "'); | 60 buffer.add(' "mappings": "'); |
| 61 entries.forEach((_Entry entry) => writeEntry(entry, targetFile, buffer)); | 61 entries.forEach((SourceMapEntry entry) => writeEntry(entry, targetFile, buff
er)); |
| 62 buffer.add('",\n'); | 62 buffer.add('",\n'); |
| 63 buffer.add(' "sources": '); | 63 buffer.add(' "sources": '); |
| 64 JSON.printOn(sourceUrlList, buffer); | 64 JSON.printOn(sourceUrlList, buffer); |
| 65 buffer.add(',\n'); | 65 buffer.add(',\n'); |
| 66 buffer.add(' "names": '); | 66 buffer.add(' "names": '); |
| 67 JSON.printOn(sourceNameList, buffer); | 67 JSON.printOn(sourceNameList, buffer); |
| 68 buffer.add('\n}\n'); | 68 buffer.add('\n}\n'); |
| 69 return buffer.toString(); | 69 return buffer.toString(); |
| 70 } | 70 } |
| 71 | 71 |
| 72 void writeEntry(_Entry entry, SourceFile targetFile, StringBuffer output) { | 72 void writeEntry(SourceMapEntry entry, SourceFile targetFile, StringBuffer outp
ut) { |
| 73 int targetLine = targetFile.getLine(entry.targetOffset); | 73 int targetLine = targetFile.getLine(entry.targetOffset); |
| 74 int targetColumn = targetFile.getColumn(targetLine, entry.targetOffset); | 74 int targetColumn = targetFile.getColumn(targetLine, entry.targetOffset); |
| 75 String sourceUrl; | |
| 76 int sourceLine; | |
| 77 int sourceColumn; | |
| 78 SourceFile sourceFile = entry.sourceFile; | |
| 79 // TODO(podivilov): make sure entries are always associated with the right | |
| 80 // source file. | |
| 81 if (sourceFile != null && entry.sourceOffset < sourceFile.text.length) { | |
| 82 sourceUrl = sourceFile.filename; | |
| 83 sourceLine = sourceFile.getLine(entry.sourceOffset); | |
| 84 sourceColumn = sourceFile.getColumn(sourceLine, entry.sourceOffset); | |
| 85 } | |
| 86 String sourceName = entry.sourceName; | |
| 87 | 75 |
| 88 if (targetLine > previousTargetLine) { | 76 if (targetLine > previousTargetLine) { |
| 89 for (int i = previousTargetLine; i < targetLine; ++i) { | 77 for (int i = previousTargetLine; i < targetLine; ++i) { |
| 90 output.add(';'); | 78 output.add(';'); |
| 91 } | 79 } |
| 92 previousTargetLine = targetLine; | 80 previousTargetLine = targetLine; |
| 93 previousTargetColumn = 0; | 81 previousTargetColumn = 0; |
| 94 firstEntryInLine = true; | 82 firstEntryInLine = true; |
| 95 } | 83 } |
| 96 | 84 |
| 97 if (!firstEntryInLine) { | 85 if (!firstEntryInLine) { |
| 98 output.add(','); | 86 output.add(','); |
| 99 } | 87 } |
| 100 firstEntryInLine = false; | 88 firstEntryInLine = false; |
| 101 | 89 |
| 102 encodeVLQ(output, targetColumn - previousTargetColumn); | 90 encodeVLQ(output, targetColumn - previousTargetColumn); |
| 103 previousTargetColumn = targetColumn; | 91 previousTargetColumn = targetColumn; |
| 104 | 92 |
| 105 if (sourceUrl === null) { | 93 if (entry.sourceLocation === null) return; |
| 106 return; | 94 |
| 107 } | 95 String sourceUrl = entry.sourceLocation.getSourceUrl(); |
| 96 int sourceLine = entry.sourceLocation.getLine(); |
| 97 int sourceColumn = entry.sourceLocation.getColumn(); |
| 98 String sourceName = entry.sourceLocation.getSourceName(); |
| 108 | 99 |
| 109 int sourceUrlIndex = indexOf(sourceUrlList, sourceUrl, sourceUrlMap); | 100 int sourceUrlIndex = indexOf(sourceUrlList, sourceUrl, sourceUrlMap); |
| 110 encodeVLQ(output, sourceUrlIndex - previousSourceUrlIndex); | 101 encodeVLQ(output, sourceUrlIndex - previousSourceUrlIndex); |
| 111 previousSourceUrlIndex = sourceUrlIndex; | 102 previousSourceUrlIndex = sourceUrlIndex; |
| 112 | 103 |
| 113 encodeVLQ(output, sourceLine - previousSourceLine); | 104 encodeVLQ(output, sourceLine - previousSourceLine); |
| 114 previousSourceLine = sourceLine; | 105 previousSourceLine = sourceLine; |
| 115 encodeVLQ(output, sourceColumn - previousSourceColumn); | 106 encodeVLQ(output, sourceColumn - previousSourceColumn); |
| 116 previousSourceColumn = sourceColumn; | 107 previousSourceColumn = sourceColumn; |
| 117 | 108 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 144 int digit = value & VLQ_BASE_MASK; | 135 int digit = value & VLQ_BASE_MASK; |
| 145 value >>= VLQ_BASE_SHIFT; | 136 value >>= VLQ_BASE_SHIFT; |
| 146 if (value > 0) { | 137 if (value > 0) { |
| 147 digit |= VLQ_CONTINUATION_BIT; | 138 digit |= VLQ_CONTINUATION_BIT; |
| 148 } | 139 } |
| 149 output.add(BASE64_DIGITS[digit]); | 140 output.add(BASE64_DIGITS[digit]); |
| 150 } while (value > 0); | 141 } while (value > 0); |
| 151 } | 142 } |
| 152 } | 143 } |
| 153 | 144 |
| 154 class _Entry { | 145 class SourceMapEntry { |
| 146 SourceFileLocation sourceLocation; |
| 147 int targetOffset; |
| 148 |
| 149 SourceMapEntry(this.sourceLocation, this.targetOffset); |
| 150 } |
| 151 |
| 152 class SourceFileLocation { |
| 155 SourceFile sourceFile; | 153 SourceFile sourceFile; |
| 156 int sourceOffset; | 154 Token token; |
| 157 String sourceName; | 155 int line; |
| 158 int targetOffset; | 156 |
| 159 _Entry(this.sourceFile, this.sourceOffset, this.sourceName, | 157 SourceFileLocation(this.sourceFile, this.token) { |
| 160 this.targetOffset); | 158 assert(token.charOffset < sourceFile.text.length); |
| 159 } |
| 160 |
| 161 String getSourceUrl() => sourceFile.filename; |
| 162 |
| 163 int getLine() { |
| 164 if (line == null) line = sourceFile.getLine(token.charOffset); |
| 165 return line; |
| 166 } |
| 167 |
| 168 int getColumn() => sourceFile.getColumn(getLine(), token.charOffset); |
| 169 |
| 170 String getSourceName() { |
| 171 if (token.isIdentifier()) return token.slowToString(); |
| 172 return null; |
| 173 } |
| 161 } | 174 } |
| OLD | NEW |