Unverified Commit c5ad1067 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Handle errors in `compute()` by propagating them to the Future. (#24848)

parent 273364e2
...@@ -49,6 +49,7 @@ Future<R> compute<Q, R>(ComputeCallback<Q, R> callback, Q message, { String debu ...@@ -49,6 +49,7 @@ Future<R> compute<Q, R>(ComputeCallback<Q, R> callback, Q message, { String debu
final Flow flow = Flow.begin(); final Flow flow = Flow.begin();
Timeline.startSync('$debugLabel: start', flow: flow); Timeline.startSync('$debugLabel: start', flow: flow);
final ReceivePort resultPort = ReceivePort(); final ReceivePort resultPort = ReceivePort();
final ReceivePort errorPort = ReceivePort();
Timeline.finishSync(); Timeline.finishSync();
final Isolate isolate = await Isolate.spawn<_IsolateConfiguration<Q, R>>( final Isolate isolate = await Isolate.spawn<_IsolateConfiguration<Q, R>>(
_spawn, _spawn,
...@@ -61,13 +62,32 @@ Future<R> compute<Q, R>(ComputeCallback<Q, R> callback, Q message, { String debu ...@@ -61,13 +62,32 @@ Future<R> compute<Q, R>(ComputeCallback<Q, R> callback, Q message, { String debu
), ),
errorsAreFatal: true, errorsAreFatal: true,
onExit: resultPort.sendPort, onExit: resultPort.sendPort,
onError: errorPort.sendPort,
); );
final R result = await resultPort.first; final Completer<R> result = Completer<R>();
errorPort.listen((dynamic errorData) {
assert(errorData is List<dynamic>);
assert(errorData.length == 2);
final Exception exception = Exception(errorData[0]);
final StackTrace stack = StackTrace.fromString(errorData[1]);
if (result.isCompleted) {
Zone.current.handleUncaughtError(exception, stack);
} else {
result.completeError(exception, stack);
}
});
resultPort.listen((dynamic resultData) {
assert(resultData == null || resultData is R);
if (!result.isCompleted)
result.complete(resultData);
});
await result.future;
Timeline.startSync('$debugLabel: end', flow: Flow.end(flow.id)); Timeline.startSync('$debugLabel: end', flow: Flow.end(flow.id));
resultPort.close(); resultPort.close();
errorPort.close();
isolate.kill(); isolate.kill();
Timeline.finishSync(); Timeline.finishSync();
return result; return result.future;
} }
@immutable @immutable
...@@ -92,9 +112,7 @@ void _spawn<Q, R>(_IsolateConfiguration<Q, R> configuration) { ...@@ -92,9 +112,7 @@ void _spawn<Q, R>(_IsolateConfiguration<Q, R> configuration) {
R result; R result;
Timeline.timeSync( Timeline.timeSync(
'${configuration.debugLabel}', '${configuration.debugLabel}',
() { () { result = configuration.apply(); },
result = configuration.apply();
},
flow: Flow.step(configuration.flowId), flow: Flow.step(configuration.flowId),
); );
Timeline.timeSync( Timeline.timeSync(
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/foundation.dart';
import '../flutter_test_alternative.dart';
int test1(int value) {
return value + 1;
}
int test2(int value) {
throw 2;
}
void main() {
test('compute()', () async {
expect(await compute(test1, 0), 1);
expect(compute(test2, 0), throwsA(isInstanceOf<Exception>()));
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment