blob: 235e380292d5013dbc79fcb8d507c143460d44de [file] [log] [blame]
// Copyright (c) 2018, 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.
import 'dart:io';
import 'package:dart2js_tools/src/util.dart';
/// Script to show a text representation of the inlining data attached to
/// source-map files.
///
/// This expands the push/pop operations and checks simple invariants (e.g. that
/// the stack is always empty at the beginning of a function).
main(List<String> args) {
if (args.length != 1) {
print('usage: show_inline_data.dart <js-file>');
exit(1);
}
var uri = Uri.base.resolve(args[0]);
var provider = new CachingFileProvider();
var mapping = provider.mappingFor(uri);
var starts = functionStarts(provider.sourcesFor(uri));
var file = provider.fileFor(uri);
var frames = mapping!.frames;
var offsets = frames.keys.toList()..sort();
var sb = new StringBuffer();
int depth = 0;
int? lastFunctionStart = null;
for (var offset in offsets) {
int functionStart = nextFunctionStart(starts, offset, lastFunctionStart);
if (lastFunctionStart == null || functionStart > lastFunctionStart) {
sb.write('\n${location(starts[functionStart], file)}: function start\n');
if (depth != 0) {
sb.write(
"[invalid] function start with non-zero depth: $depth\n");
}
lastFunctionStart = functionStart;
}
var offsetPrefix = '${location(offset, file)}:';
var pad = ' ' * offsetPrefix.length;
sb.write(offsetPrefix);
bool first = true;
for (var frame in frames[offset]!) {
if (!first) sb.write('$pad');
sb.write(' $frame\n');
first = false;
if (frame.isPush) depth++;
if (frame.isPop) depth--;
if (frame.isEmpty && depth != 0) {
sb.write("[invalid] pop-empty with non-zero depth: $depth\n");
}
if (!frame.isEmpty && depth == 0) {
sb.write("[invalid] non-empty pop with zero depth: $depth\n");
}
if (depth < 0) {
sb.write("[invalid] negative depth: $depth\n");
}
}
}
print('$sb');
}
var _functionDeclarationRegExp = new RegExp(r':( )?function\(');
List<int> functionStarts(String sources) {
List<int> result = [];
int index = sources.indexOf(_functionDeclarationRegExp);
while (index != -1) {
result.add(index + 2);
index = sources.indexOf(_functionDeclarationRegExp, index + 1);
}
return result;
}
int nextFunctionStart(List<int> starts, int offset, int? last) {
int j = last ?? 0;
for (; j < starts.length && starts[j] <= offset; j++);
return j - 1;
}
String location(int offset, file) {
var line = file.getLine(offset) + 1;
var column = file.getColumn(offset) + 1;
var location = '$offset ($line:$column)';
return location + (' ' * (16 - location.length));
}