-
Notifications
You must be signed in to change notification settings - Fork 1.7k
[dart2wasm] Try/catch in an async function doesn't emit catch_all
for JS exceptions
#55457
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
Comments
I think probably the issue is that the current mechanisms for async try/catch of JS exceptions actually do work if the exception is thrown asynchronously, because it looks like in the async context we do catch JS exceptions and probably convert them to a dart exception: sdk/pkg/dart2wasm/lib/async.dart Line 793 in 8af6f94
So the try/catch lowering assumes that it has already been converted to a dart exception with the |
Related? #55466 |
We need the Test file: import 'dart:js_interop';
@JS()
external void eval(String code);
@JS()
external void throwFromJS();
void defineFunctions() {
eval(r'''
globalThis.throwFromJS = function() {
throw 'exception from JS';
};
''');
}
Future<void> catchInAsync() async {
try {
throwFromJS();
} catch (e) {
print("Error caugh in async function");
} finally {
print("Finally block in async function");
}
}
void catchInSync() {
try {
throwFromJS();
} catch (e) {
print("Error caugh in sync function");
} finally {
print("Finally block in sync function");
}
}
Future<void> main() async {
await catchInAsync();
catchInSync();
}
This is right, if the JS exception is caught in an import 'dart:js_interop';
@JS()
external void eval(String code);
@JS()
external void throwFromJS();
void defineFunctions() {
eval(r'''
globalThis.throwFromJS = function() {
throw 'exception from JS';
};
''');
}
Future<void> catchInAsync() async {
try {
throwFromJS();
} catch (e) {
print("Error caugh in async function");
} finally {
print("Finally block in async function");
}
}
Future<void> main() async {
try {
await catchInAsync();
} catch (e) {
print("Exception caught in main");
}
} Here The fix should just be a matter of adding We can actually avoid |
One other possibility that has occurred to me is to actually wrap every JS interop entry point with a On the other hand, exceptions flowing through an export that comes from a |
Fix in progress in https://dart-review.googlesource.com/c/sdk/+/363000. |
I wonder if we can get this information by using |
That is also a possibility, but |
This cherry-picks commits: 6de879e - [dart2wasm] Fix exception handling in async functions 7e237a1 - [dart2wasm] Small refactoring in async code generator eabb2b3 - [dart2wasm] Catch JS exceptions in async functions e44bc22 - [dart2wasm] Fix bug in restoration of `this` in async functions. 350954a - [dart2wasm] Fix `this` restoration code in sync* handling. 8ccb412 - [dart2wasm] Move type parameter bounds checks & parameter type check logic together with logic setting up variables e7dde83 - [dart2wasm] Port VM fix for #52083 (sync*) 3863e78 - [dart2wasm] Move yield finder to a shared library 829261e - [dart2wasm] Move async compiler utilities to state_machine library fab56db - [dart2wasm] Move common code generation routines to state_machine, fix sync* Bugs: #55347, #55457, #51343, #51342 Cherry-pick: https://dart-review.googlesource.com/c/sdk/+/368300 Cherry-pick-request: #55847 Change-Id: I0a4186533fbdf4c5727911295ad48696a90f715f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/368300 Commit-Queue: Ömer Ağacan <omersa@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Martin Kustermann <kustermann@google.com>
If the catch guard in a
try/catch
block is general enough to cover JS exceptions, the lowering to wasm needs to include acatch_all
block, as that's the only way to catch JS exceptions (they have no exception tag). This works in synchronous functions. For example, in the following code:The try/catch block lowers to:
However, if this is in an async context instead, the
catch_all
block is not actually emitted. For example, in the same code, but in with an asyncmain
function:The try/catch block lowers to:
Notice the missing
catch_all
block. As a result, JS exceptions escape this try/catch and cause failures.The specific customer who this is affecting is the flutter firebase packages, which have this try/catch here: https://github.com/firebase/flutterfire/blob/213608cf7d889aeb60084ef5fb74a1e74178d7ba/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart#L254 which normally allows them to continue and properly initialize the firebase app.
The text was updated successfully, but these errors were encountered: