mapStackTrace function

StackTrace mapStackTrace(
  1. Mapping sourceMap,
  2. StackTrace stackTrace, {
  3. bool minified = false,
  4. Map<String, Uri>? packageMap,
  5. Uri? sdkRoot,
})

Convert stackTrace, a stack trace generated by dart2js-compiled JavaScript, to a native-looking stack trace using sourceMap.

minified indicates whether or not the dart2js code was minified. If it hasn't, this tries to clean up the stack frame member names.

The packageMap maps package names to the base uri used to resolve the package: uris for those packages. It is used to it's used to reconstruct package: URIs for stack frames that come from packages.

sdkRoot is the URI surfaced in the stack traces for SDK libraries. If it's passed, stack frames from the SDK will have dart: URLs.

Implementation

StackTrace mapStackTrace(Mapping sourceMap, StackTrace stackTrace,
    {bool minified = false, Map<String, Uri>? packageMap, Uri? sdkRoot}) {
  if (stackTrace is Chain) {
    return Chain(stackTrace.traces.map((trace) {
      return Trace.from(mapStackTrace(sourceMap, trace,
          minified: minified, packageMap: packageMap, sdkRoot: sdkRoot));
    }));
  }

  var sdkLib = sdkRoot == null ? null : '$sdkRoot/lib';

  var trace = Trace.from(stackTrace);
  return Trace(trace.frames.map((frame) {
    var line = frame.line;
    // If there's no line information, there's no way to translate this frame.
    // We could return it as-is, but these lines are usually not useful anyways.
    if (line == null) return null;

    // If there's no column, try using the first column of the line.
    var column = frame.column ?? 0;

    // Subtract 1 because stack traces use 1-indexed lines and columns and
    // source maps uses 0-indexed.
    var span =
        sourceMap.spanFor(line - 1, column - 1, uri: frame.uri.toString());

    // If we can't find a source span, ignore the frame. It's probably something
    // internal that the user doesn't care about.
    if (span == null) return null;

    var sourceUrl = span.sourceUrl.toString();
    if (sdkLib != null && p.url.isWithin(sdkLib, sourceUrl)) {
      sourceUrl = 'dart:' + p.url.relative(sourceUrl, from: sdkLib);
    } else if (packageMap != null) {
      for (var package in packageMap.keys) {
        var packageUrl = packageMap[package].toString();
        if (!p.url.isWithin(packageUrl, sourceUrl)) continue;

        sourceUrl =
            'package:$package/' + p.url.relative(sourceUrl, from: packageUrl);
        break;
      }
    }

    return Frame(
        Uri.parse(sourceUrl),
        span.start.line + 1,
        span.start.column + 1,
        // If the dart2js output is minified, there's no use trying to prettify
        // its member names. Use the span's identifier if available, otherwise
        // use the minified member name.
        minified
            ? (span.isIdentifier ? span.text : frame.member)
            : _prettifyMember(frame.member!));
  }).whereType<Frame>());
}