aa246f6588
Reduces the noise when disallowing implicit dynamic. Change-Id: I98b03cb675ecd4b9e7f4135efa274fb57eb87832 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/104164 Reviewed-by: Nicholas Shahan <nshahan@google.com> Commit-Queue: Nate Bosch <nbosch@google.com>
121 lines
3.9 KiB
Dart
121 lines
3.9 KiB
Dart
// Copyright (c) 2017, 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.
|
|
|
|
/// Standalone utility that manages loading source maps for all Dart scripts
|
|
/// on the page compiled with DDC.
|
|
///
|
|
/// Example JavaScript usage:
|
|
/// $dartStackTraceUtility.addLoadedListener(function() {
|
|
/// // All Dart source maps are now loaded. It is now safe to start your
|
|
/// // Dart application compiled with DDC.
|
|
/// dart_library.start('your_dart_application');
|
|
/// })
|
|
///
|
|
/// If $dartStackTraceUtility is set, the dart:core StackTrace class calls
|
|
/// $dartStackTraceUtility.mapper(someJSStackTrace)
|
|
/// to apply source maps.
|
|
///
|
|
/// This utility can be compiled to JavaScript using Dart2JS while the rest
|
|
/// of the application is compiled with DDC or could be compiled with DDC.
|
|
|
|
@JS()
|
|
library stack_trace_mapper;
|
|
|
|
import 'package:js/js.dart';
|
|
import 'package:path/path.dart' as path;
|
|
import 'source_map_stack_trace.dart';
|
|
import 'package:source_maps/source_maps.dart';
|
|
import 'package:source_span/source_span.dart';
|
|
import 'package:stack_trace/stack_trace.dart';
|
|
|
|
typedef void ReadyCallback();
|
|
|
|
/// Global object DDC uses to see if a stack trace utility has been registered.
|
|
@JS(r'$dartStackTraceUtility')
|
|
external set dartStackTraceUtility(DartStackTraceUtility value);
|
|
|
|
@JS(r'$dartLoader.rootDirectories')
|
|
external List get rootDirectories;
|
|
|
|
typedef String StackTraceMapper(String stackTrace);
|
|
typedef dynamic SourceMapProvider(String modulePath);
|
|
typedef void SetSourceMapProvider(SourceMapProvider provider);
|
|
|
|
@JS()
|
|
@anonymous
|
|
class DartStackTraceUtility {
|
|
external factory DartStackTraceUtility(
|
|
{StackTraceMapper mapper, SetSourceMapProvider setSourceMapProvider});
|
|
}
|
|
|
|
@JS('JSON.stringify')
|
|
external String _stringify(dynamic json);
|
|
|
|
/// Source mapping that is waits to parse source maps until they match the uri
|
|
/// of a requested source map.
|
|
///
|
|
/// This improves startup performance compared to using MappingBundle directly.
|
|
/// The unparsed data for the source maps must still be loaded before
|
|
/// LazyMapping is used.
|
|
class LazyMapping extends Mapping {
|
|
MappingBundle _bundle = MappingBundle();
|
|
SourceMapProvider _provider;
|
|
|
|
LazyMapping(this._provider);
|
|
|
|
List toJson() => _bundle.toJson();
|
|
|
|
@override
|
|
SourceMapSpan spanFor(int line, int column,
|
|
{Map<String, SourceFile> files, String uri}) {
|
|
if (uri == null) {
|
|
throw ArgumentError.notNull('uri');
|
|
}
|
|
|
|
if (!_bundle.containsMapping(uri)) {
|
|
var rawMap = _provider(uri);
|
|
if (rawMap != null) {
|
|
var strMap = rawMap is String ? rawMap : _stringify(rawMap);
|
|
var mapping = parse(strMap) as SingleMapping;
|
|
mapping
|
|
..targetUrl = uri
|
|
..sourceRoot = '${path.dirname(uri)}/';
|
|
_bundle.addMapping(mapping);
|
|
}
|
|
}
|
|
var span = _bundle.spanFor(line, column, files: files, uri: uri);
|
|
// TODO(jacobr): we shouldn't have to filter out invalid sourceUrl entries
|
|
// here.
|
|
if (span == null || span.start.sourceUrl == null) return null;
|
|
var pathSegments = span.start.sourceUrl.pathSegments;
|
|
if (pathSegments.isNotEmpty && pathSegments.last == 'null') return null;
|
|
return span;
|
|
}
|
|
}
|
|
|
|
LazyMapping _mapping;
|
|
|
|
List<String> roots = rootDirectories.map((s) => '$s').toList();
|
|
|
|
String mapper(String rawStackTrace) {
|
|
if (_mapping == null) {
|
|
// This should not happen if the user has waited for the ReadyCallback
|
|
// to start the application.
|
|
throw StateError('Source maps are not done loading.');
|
|
}
|
|
var trace = Trace.parse(rawStackTrace);
|
|
return mapStackTrace(_mapping, trace, roots: roots).toString();
|
|
}
|
|
|
|
void setSourceMapProvider(SourceMapProvider provider) {
|
|
_mapping = LazyMapping(provider);
|
|
}
|
|
|
|
void main() {
|
|
// Register with DDC.
|
|
dartStackTraceUtility = DartStackTraceUtility(
|
|
mapper: allowInterop(mapper),
|
|
setSourceMapProvider: allowInterop(setSourceMapProvider));
|
|
}
|