Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Source-mapped Stack Trace Doesn't Match Chrome #18

Open
todbachman-wf opened this issue Oct 17, 2016 · 1 comment
Open

Source-mapped Stack Trace Doesn't Match Chrome #18

todbachman-wf opened this issue Oct 17, 2016 · 1 comment

Comments

@todbachman-wf
Copy link
Contributor

todbachman-wf commented Oct 17, 2016

We are having trouble with the reliability of applying source maps to stack traces. One of the things I'm finding is Mapping.spanFor sometimes returns null when I'd have expected to get a specific line in my code. It's possible that the way we are using source_maps is at fault, so if that's the case please let me know!

Here's a simple example that demonstrates the problem. It renders a single button that throws an exception when clicked. It catches the exception and applies the source map to the exception and then rethrows the exception so we can let Chrome handle it too.

pubspec.yaml:

name: stack_trace_parser

dependencies:
  browser: ">=0.10.0 <0.11.0"
  source_maps: ^0.10.1
  stack_trace: ^1.6.6

transformers:
- $dart2js:
    sourceMaps: true

web/index.html:

<html>
<head>
    <title>Stack Trace Parsing</title>
</head>
<body>
    <script type="application/dart" src="main.dart"></script>
    <script src="/packages/browser/dart.js"></script>
</body>
</html>

web/main.dart

import 'dart:async';
import 'dart:html';

import 'package:stack_trace_parser/stack_trace_parser.dart';

Future main() async {
  await loadSourceMap();
  addElements();
}

void addElements() {
  querySelector('body')
    ..append(new ButtonElement()
      ..text = 'Throw Exception'
      ..onClick.listen(_handleExceptionButton));
}

void _handleExceptionButton(_) {
  try {
    throw new IntegerDivisionByZeroException();
  } catch (e, stackTrace) {
    print(mapStackTrace(stackTrace));
    throw e;
  }
}

lib/stack_trace_parser.dart:

import 'dart:async';
import 'dart:html';

import 'package:source_maps/source_maps.dart';
import 'package:stack_trace/stack_trace.dart';

Mapping _sourceMap;

Future loadSourceMap() async {
  _sourceMap = parse(await HttpRequest.getString('main.dart.js.map'));
}

StackTrace mapStackTrace(StackTrace stackTrace) {
  var frames = new Trace.from(stackTrace).frames.map((Frame frame) {
    var span = _sourceMap.spanFor(frame.line - 1, (frame.column ?? 1) - 1);
    if (span == null) {
      return frame;
    }
    return new Frame(
        span.sourceUrl, span.start.line + 1, span.start.column + 1, span.text);
  });
  return new Trace(frames);
}

Steps to generate stack traces:

  1. Open Chrome
  2. Open the dev tools
  3. Edit dev tools settings and ensure Enable JavaScript source maps is checked
  4. pub serve
  5. Navigate to localhost:8080 in Chrome
  6. Click the button labeled Throw Exception
  7. Switch to the dev tools Console
  8. You should see the output from us applying the source map followed by Chrome handling the exception and applying the source map itself:
    image

Notice that our output differs on the second line of the stack trace from that of Chrome. In our case Mapping.spanFor returned null and we just passed the stack trace frame through unchanged. On the other hand, Chrome was able to use the source map to identify a line number in the original source file, main.dart (although the actual line number is off by two 😉 ).

Am I using the source_maps API correctly? If so, it seems like there might be an issue here in the source map parser.

@todbachman-wf
Copy link
Contributor Author

FYI -- I've submitted a separate issue to the Dart SDK because it appears line numbers reported by Chrome in stack traces don't line up with the correct locations in source files. dart-lang/sdk#27600 I suppose it's possible the two issues could be related.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant