Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Side by Side Diff: pkg/dev_compiler/web/stack_trace_mapper.dart

Issue 2735303002: Make all DDC internal stack traces apply source maps. (Closed)
Patch Set: Make all DDC internal stack traces apply source maps. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/dev_compiler/tool/input_sdk/private/js_helper.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
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.
4
5 /// Standalone utility that manages loading source maps for all Dart scripts
6 /// on the page compiled with DDC.
7 ///
8 /// Example JavaScript usage:
9 /// $dartStackTraceUtility.addLoadedListener(function() {
10 /// // All Dart source maps are now loaded. It is now safe to start your
11 /// // Dart application compiled with DDC.
12 /// dart_library.start('your_dart_application');
13 /// })
14 ///
15 /// If $dartStackTraceUtility is set, the dart:core StackTrace class calls
16 /// $dartStackTraceUtility.mapper(someJSStackTrace)
17 /// to apply source maps.
18 ///
19 /// This utility can be compiled to JavaScript using Dart2JS while the rest
20 /// of the application is compiled with DDC or could be compiled with DDC.
21
22 @JS()
23 library stack_trace_mapper;
24
25 import 'dart:async';
26 import 'dart:html';
27
28 import 'package:js/js.dart';
29 import 'package:path/path.dart' as path;
30 import 'package:source_map_stack_trace/source_map_stack_trace.dart';
31 import 'package:source_maps/source_maps.dart';
32 import 'package:source_span/source_span.dart';
33 import 'package:stack_trace/stack_trace.dart';
34
35 typedef void ReadyCallback();
36
37 /// Global object DDC uses to see if a stack trace utility has been registered.
38 @JS(r'$dartStackTraceUtility')
39 external set dartStackTraceUtility(DartStackTraceUtility value);
40
41 typedef String StackTraceMapper(String stackTrace);
42 typedef dynamic LoadSourceMaps(List<String> scripts, ReadyCallback callback);
43
44 @JS()
45 @anonymous
46 class DartStackTraceUtility {
47 external factory DartStackTraceUtility(
48 {StackTraceMapper mapper, LoadSourceMaps loadSourceMaps});
49 }
50
51 /// Source mapping that is waits to parse source maps until they match the uri
52 /// of a requested source map.
53 ///
54 /// This improves startup performance compared to using MappingBundle directly.
55 /// The unparsed data for the source maps must still be loaded before
56 /// LazyMapping is used.
57 class LazyMapping extends Mapping {
58 MappingBundle _bundle = new MappingBundle();
59
60 /// Map from url to unparsed source map.
61 Map<String, String> _sourceMaps;
62
63 LazyMapping(this._sourceMaps) {}
64
65 List toJson() => _bundle.toJson();
66
67 SourceMapSpan spanFor(int line, int column,
68 {Map<String, SourceFile> files, String uri}) {
69 if (uri == null) {
70 throw new ArgumentError.notNull('uri');
71 }
72 var rawMap = _sourceMaps[uri];
73
74 if (rawMap != null && rawMap.isNotEmpty && !_bundle.containsMapping(uri)) {
75 SingleMapping mapping = parse(rawMap);
76 mapping
77 ..targetUrl = uri
78 ..sourceRoot = '${path.dirname(uri)}/';
79 _bundle.addMapping(mapping);
80 }
81
82 return _bundle.spanFor(line, column, files: files, uri: uri);
83 }
84 }
85
86 String _toSourceMapLocation(String url) {
87 // The url may have cache busting query parameters which we need to maintain
88 // in the source map url.
89 // For example:
90 // http://localhost/foo.js?cachebusting=23419
91 // Should get source map
92 // http://localhost/foo.js.map?cachebusting=23419
93 var uri = Uri.parse(url);
94 return uri.replace(path: '${uri.path}.map').toString();
95 }
96
97 /// Load a source map for the specified url.
98 ///
99 /// Returns a null string rather than reporting an error if the file cannot be
100 /// found as we don't want to throw errors if a few source maps are missing.
101 Future<String> loadSourceMap(String url) async {
102 try {
103 return await HttpRequest.getString(_toSourceMapLocation(url));
104 } catch (e) {
105 return null;
106 }
107 }
108
109 LazyMapping _mapping;
110
111 String mapper(String rawStackTrace) {
112 if (_mapping == null) {
113 // This should not happen if the user has waited for the ReadyCallback
114 // to start the application.
115 throw new StateError('Source maps are not done loading.');
116 }
117 return mapStackTrace(_mapping, new Trace.parse(rawStackTrace)).toString();
118 }
119
120 Future<Null> loadSourceMaps(
121 List<String> scripts, ReadyCallback callback) async {
122 List<Future<String>> sourceMapFutures =
123 scripts.map((script) => loadSourceMap(script)).toList();
124 List<String> sourceMaps = await Future.wait(sourceMapFutures);
125 _mapping = new LazyMapping(new Map.fromIterables(scripts, sourceMaps));
126 callback();
127 }
128
129 main() {
130 // Register with DDC.
131 dartStackTraceUtility = new DartStackTraceUtility(
132 mapper: allowInterop(mapper),
133 loadSourceMaps: allowInterop(loadSourceMaps));
134 }
OLDNEW
« no previous file with comments | « pkg/dev_compiler/tool/input_sdk/private/js_helper.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698