Comments (7)
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 $tag0
tag. However, this doesn't actually work when the exception is thrown synchronously, because the try/catch lowering is responsible for directly catching the thrown exception (rather than something transformed by the async error handling context)
from sdk.
Related? #55466
from sdk.
We need the try_catch
blocks we have in the sync code generator in try-finally
and try-catch
compilers in async code generator as well.
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();
}
catchInSync
works as expected, but catchInAsync
crashes as the JS exception isn't caught.
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
This is right, if the JS exception is caught in an await
it's handled. Example:
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 main
catches the JS exception, but catchInAsync
doesn't (because of this bug).
The fix should just be a matter of adding catch_all
blocks in try-finally
and try-catch
blocks.
We can actually avoid catch_all
blocks when a call is known to not make JS calls because the only reason why we have catch_all
is to catch JS exceptions. I think we probably doesn't have this information today. I'll file an issue for this for now. (filed #55470)
from sdk.
One other possibility that has occurred to me is to actually wrap every JS interop entry point with a try/catch
in JavaScript that converts any JS exception to a dart exception right at the JS/Wasm boundary. That would theoretically allow us to eliminate the catch_all
blocks from all the dart2wasm code completely, since it can assume that any exceptions flowing through the wasm code will already be converted to a dart exception. This also would allow us to get more detailed/complete information about the JS exceptions, since we can actually introspect info about the JS exception (such as stack trace, exception type, message, etc) in a JS catch block that is not accessible with a catch_all
instruction in wasm.
On the other hand, exceptions flowing through an export that comes from a @Native
annotation might disobey this assumption. Also the performance overhead of wrapping all JS interop calls with a try/catch block is unclear. JIT may be fairly smart at eliminating the overhead for calls that can't actually throw.
from sdk.
Fix in progress in https://dart-review.googlesource.com/c/sdk/+/363000.
from sdk.
This also would allow us to get more detailed/complete information about the JS exceptions, since we can actually introspect info about the JS exception (such as stack trace, exception type, message, etc)
I wonder if we can get this information by using catch_all_ref
instead of catch_all
, and implementing JS functions to get the stack trace (and other info) from passed exception references.
from sdk.
That is also a possibility, but catch_all_ref
is fairly recent and browser support is limited. Whereas catching the JS exception in JS would be supported by all browsers today.
from sdk.
Related Issues (20)
- No completion for target of property access when it is assigned HOT 1
- [breaking change] Consider NEL (U+0085) not whitespace for trim, trimLeft, trimRight HOT 2
- bug: Class constructor <class_name> cannot be invoked without 'new' HOT 6
- [breaking change] Change parameter type of `importModule` from `String` to `JSAny` HOT 6
- [CP] Update with DevTools that does not fail heap snapshotting. HOT 6
- [frontend_server] Ability to change `output-dill`
- [doc/ffi] `NativeFinalizer` shutdown guarantees HOT 2
- What if VScode would suggest the `~/` operator if the `/` operator does not exist? HOT 2
- [Wasm] illegal cast exception when trying to use Firebase Auth with Flutter HOT 3
- "Exception:: Missing implementation of visitAugmentedExpression" HOT 1
- Semantics of `dart:js_interop`s `Function.toJS` extension HOT 2
- Make `dart compile wasm -O4` not omit explicit type checks HOT 3
- Implement the macros feature in the analyzer HOT 4
- [vm] Optimizer can keep object longer alive due to CSE/Store-to-Load of WeakReference.target HOT 6
- [vm/ffi] Native assets dylib handles should be cached
- Dart fix not working with `--code` and part of HOT 6
- [vm/ffi] Native asset dynamic libraries should be `dlclose`d on isolate (group) shutdown
- Improve VM's JSON decoder HOT 4
- [vm/ffi] Native asset resolution via embedder HOT 1
- dart fix with both --dry-run and --apply
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from sdk.