blob: ac860f46be1b0c01540da787f594390692724bd7 [file] [log] [blame]
// Copyright (c) 2016, 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.
// @dart = 2.7
/// Loads a human-readable source map and outputs the source map file for it.
library save;
import 'dart:convert';
import 'dart:io';
import 'package:source_maps/source_maps.dart';
import '../helpers/lax_json.dart' as lazon;
void main(List<String> args) {
if (args.isEmpty) {
print('''
Usage: save <dir-containing 'out.js.map2'>
or: save <human-readable-source-map-file> [<source-map-file>]''');
exit(1);
}
File humanReadableSourceMapFile;
File sourceMapFile;
if (args.length == 1 && new Directory(args[0]).existsSync()) {
humanReadableSourceMapFile = new File('${args[0]}/out.js.map2');
sourceMapFile = new File('${args[0]}/out.js.map');
} else {
humanReadableSourceMapFile = new File(args[0]);
if (args.length > 1) {
sourceMapFile = new File(args[1]);
}
}
String humanReadableSourceMap = humanReadableSourceMapFile.readAsStringSync();
SingleMapping mapping =
convertFromHumanReadableSourceMap(humanReadableSourceMap);
if (sourceMapFile != null) {
sourceMapFile.writeAsStringSync(json.encoder.convert(mapping.toJson()));
} else {
print(new JsonEncoder.withIndent(' ').convert(mapping.toJson()));
}
}
SingleMapping convertFromHumanReadableSourceMap(String json) {
Map inputMap = lazon.decode(json);
Map urls = inputMap['sources'];
List<String> sources = new List<String>.filled(urls.length, null);
urls.forEach((Object index, Object url) {
int i = int.parse(index);
assert(sources[i] == null);
sources[i] = url;
});
List lines = inputMap['lines'];
Map<String, int> names = <String, int>{};
Map<int, TargetLineEntry> lineEntryMap = {};
for (Map line in lines) {
String targetString = line['target'];
String sourceString = line['source'];
String name = line['name'];
int nameIndex;
if (name != null) {
nameIndex = names.putIfAbsent(name, () => names.length);
}
int lineNo;
int columnStart;
int columnEnd;
if (targetString != null) {
int commaPos = targetString.indexOf(',');
lineNo = int.parse(targetString.substring(0, commaPos)) - 1;
if (lineNo < 0) {
throw new ArgumentError('target line must be > 0: $lineNo');
}
targetString = targetString.substring(commaPos + 1);
int dashPos = targetString.indexOf('-');
columnStart = int.parse(targetString.substring(0, dashPos)) - 1;
if (columnStart < 0) {
throw new ArgumentError(
'target column start must be > 0: $columnStart');
}
targetString = targetString.substring(dashPos + 1);
if (!targetString.isEmpty) {
columnEnd = int.parse(targetString) - 1;
if (columnEnd < 0) {
throw new ArgumentError('target column end must be > 0: $columnEnd');
}
}
}
int sourceUrlId;
int sourceLine;
int sourceColumn;
if (sourceString != null) {
int colonPos = sourceString.indexOf(':');
sourceUrlId = int.parse(sourceString.substring(0, colonPos));
if (sourceUrlId < 0) {
throw new ArgumentError('source url id end must be > 0: $sourceUrlId');
} else if (sourceUrlId >= sources.length) {
throw new ArgumentError(
'source url id end must be < ${sources.length}: $sourceUrlId');
}
sourceString = sourceString.substring(colonPos + 1);
int commaPos = sourceString.indexOf(',');
sourceLine = int.parse(sourceString.substring(0, commaPos)) - 1;
if (sourceLine < 0) {
throw new ArgumentError('source line end must be > 0: $sourceLine');
}
sourceString = sourceString.substring(commaPos + 1);
sourceColumn = int.parse(sourceString) - 1;
if (sourceColumn < 0) {
throw new ArgumentError('source column must be > 0: $sourceColumn');
}
}
TargetLineEntry lineEntry =
lineEntryMap.putIfAbsent(lineNo, () => new TargetLineEntry(lineNo, []));
lineEntry.entries.add(new TargetEntry(
columnStart, sourceUrlId, sourceLine, sourceColumn, nameIndex));
if (columnEnd != null) {
lineEntry.entries.add(new TargetEntry(columnEnd));
}
}
List<TargetLineEntry> lineEntries = lineEntryMap.values.toList();
Map outputMap = {
'version': 3,
'sourceRoot': inputMap['sourceRoot'],
'file': inputMap['file'],
'sources': sources,
'names': names.keys.toList(),
'mappings': '',
};
SingleMapping mapping = new SingleMapping.fromJson(outputMap);
mapping.lines.addAll(lineEntries);
return mapping;
}