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

Unified Diff: sdk/lib/_internal/js_runtime/lib/js_helper.dart

Issue 2998943002: Add more diagnostics to the deferred loading implementation. (Closed)
Patch Set: Created 3 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/js_runtime/lib/js_helper.dart
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index bf21636123cc218295666994b8b50fb01ddad721..77058e95a9a73eab3bf4d6d7dd55cbff8f491f8d 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -3647,6 +3647,9 @@ LoadLibraryFunctionType _loadLibraryWrapper(String loadId) {
final Map<String, Future<Null>> _loadingLibraries = <String, Future<Null>>{};
final Set<String> _loadedLibraries = new Set<String>();
+/// Events used to diagnose failures from deferred loading requests.
+final List<String> _eventLog = <String>[];
sra1 2017/08/14 18:24:08 How do we get hold of this in a crash log?
Siggi Cherem (dart-lang) 2017/08/14 18:59:43 I'm attaching it on the exceptions that we throw e
sra1 2017/08/14 19:38:29 That is fine.
+
typedef void DeferredLoadCallback();
// Function that will be called every time a new deferred import is loaded.
@@ -3674,15 +3677,30 @@ Future<Null> loadDeferredLibrary(String loadId) {
// Now all hunks have been loaded, we run the needed initializers.
var isHunkInitialized = JS_EMBEDDED_GLOBAL('', IS_HUNK_INITIALIZED);
var initializer = JS_EMBEDDED_GLOBAL('', INITIALIZE_LOADED_HUNK);
- for (String hash in hashes) {
+ for (int i = 0; i < hashes.length; ++i) {
// It is possible for a hash to be repeated. This happens when two
// different parts both end up empty. Checking in the loop rather than
// pre-filtering prevents duplicate hashes leading to duplicated
// initializations.
// TODO(29572): Merge small parts.
// TODO(29635): Remove duplicate parts from tables and output files.
- if (JS('bool', '#(#)', isHunkInitialized, hash)) continue;
- JS('void', '#(#)', initializer, hash);
+ var uri = uris[i];
+ var hash = hashes[i];
+ if (JS('bool', '#(#)', isHunkInitialized, hash)) {
+ _eventLog.add(' - already initialized: $uri ($hash)');
+ continue;
+ }
+ // On strange scenarios, e.g. if js encounters parse errors, we might get
+ // an "success" callback on the script load but the hunk will be null.
+ if (JS('bool', '#(#)', isHunkLoaded, hash)) {
+ _eventLog.add(' - initialize: $uri ($hash)');
+ JS('void', '#(#)', initializer, hash);
+ } else {
+ _eventLog.add(' - missing hunk: $uri ($hash)');
+ throw new DeferredLoadException("Loading ${uris[i]} failed: "
+ "the code with hash '${hash}' was not loaded.\n"
+ "event log:\n${_eventLog.join("\n")}\n");
+ }
}
bool updated = _loadedLibraries.add(loadId);
if (updated && deferredLoadHook != null) {
@@ -3693,7 +3711,9 @@ Future<Null> loadDeferredLibrary(String loadId) {
Future<Null> _loadHunk(String hunkName) {
Future<Null> future = _loadingLibraries[hunkName];
+ _eventLog.add(' - _loadHunk: $hunkName');
if (future != null) {
+ _eventLog.add('reuse: $hunkName');
return future.then((_) => null);
}
@@ -3701,23 +3721,29 @@ Future<Null> _loadHunk(String hunkName) {
int index = uri.lastIndexOf('/');
uri = '${uri.substring(0, index + 1)}$hunkName';
+ _eventLog.add(' - download: $hunkName from $uri');
var deferredLibraryLoader = JS('', 'self.dartDeferredLibraryLoader');
Completer<Null> completer = new Completer<Null>();
void success() {
+ _eventLog.add(' - download success: $hunkName');
completer.complete(null);
}
- void failure([error, StackTrace stackTrace]) {
+ void failure(error, String context, StackTrace stackTrace) {
+ _eventLog.add(' - download failed: $hunkName (context: $context)');
_loadingLibraries[hunkName] = null;
- completer.completeError(
- new DeferredLoadException('Loading $uri failed: $error'), stackTrace);
+ stackTrace ??= StackTrace.current;
+ completer.completeError(new DeferredLoadException(
+ 'Loading $uri failed: $error\n'
+ 'event log:\n${_eventLog.join("\n")}\n'), stackTrace);
}
var jsSuccess = convertDartClosureToJS(success, 0);
var jsFailure = convertDartClosureToJS((error) {
- failure(unwrapException(error), getTraceFromException(error));
+ failure(unwrapException(error), 'js-failure-wrapper',
+ getTraceFromException(error));
}, 1);
if (JS('bool', 'typeof # === "function"', deferredLibraryLoader)) {
@@ -3725,7 +3751,7 @@ Future<Null> _loadHunk(String hunkName) {
JS('void', '#(#, #, #)', deferredLibraryLoader, uri, jsSuccess,
jsFailure);
} catch (error, stackTrace) {
- failure(error, stackTrace);
+ failure(error, "invoking dartDeferredLibraryLoader hook", stackTrace);
}
} else if (isWorker()) {
// We are in a web worker. Load the code with an XMLHttpRequest.
@@ -3745,7 +3771,7 @@ Future<Null> _loadHunk(String hunkName) {
convertDartClosureToJS((event) {
int status = JS('int', '#.status', xhr);
if (status != 200) {
- failure('Request status: $status');
+ failure('Request status: $status', 'worker xhr', null);
}
String code = JS('String', '#.responseText', xhr);
try {
@@ -3754,12 +3780,16 @@ Future<Null> _loadHunk(String hunkName) {
JS('void', '(new Function(#))()', code);
success();
} catch (error, stackTrace) {
- failure(error, stackTrace);
+ failure(error, 'evaluating the code in worker xhr', stackTrace);
}
}, 1));
- JS('void', '#.addEventListener("error", #, false)', xhr, failure);
- JS('void', '#.addEventListener("abort", #, false)', xhr, failure);
+ JS('void', '#.addEventListener("error", #, false)', xhr, (e) {
+ failure(e, 'xhr error handler', null);
+ });
+ JS('void', '#.addEventListener("abort", #, false)', xhr, (e) {
+ failure(e, 'xhr abort handler', null);
+ });
JS('void', '#.send()', xhr);
} else {
// We are in a dom-context.

Powered by Google App Engine
This is Rietveld 408576698