-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Allow runtime syntax errors to be caught #23684
Comments
It's the VM that decides what to do with a syntax error. I believe it currently makes it a top-level error and drops the current stack - it doesn't throw an error as such. Setting errors non-fatal and listening on isolate errors does work to see the errors, but it doesn't mean that recovery is possible. It's also problematic to drop the stack without executing finally blocks. That wasn't a problem before errors could be made non-fatal, but now it's visible. Example: // inner.dart
import 'dart:async';
import 'dart:isolate';
void badFn() {continue;}
void main() {
Isolate.current.setErrorsFatal(false);
RawReceivePort p = new RawReceivePort(print);
Isolate.current.addErrorListener(p.sendPort);
Timer.run(() { // Wait for the isolate calls to be handled.
new Future(() => badFn());
try {
print("1"); // Printed
badFn();
} finally {
print("2"); // Not printed!
}
});
} In general it's not nice to have a try/finally execute the try and not the finally when the isolate stays alive. It may cause logical problems if a mutex is entered but not released, or similar problems. That also makes me expect that the first syntax error will rewind right through the microtask queue code and stop executing microtasks until the next event loop event. An uncaught error in a microtask will reach the event loop, but a finally block on the way reschedules the microtask loop if there are more pending microtasks. If finally blocks are ignored, that fails too. It may be a prettier solution to throw a SyntaxError from the call-point, just as we do for other "warn-at-compile/fail-at-runtime" errors, but that's a design decision for the VM people. The spec is silent on how a syntax error must be reported. |
cc @asadovsky |
Reporting syntax errors in code that isn't executed is contrary to what the goals for Dart have been since the beginning. The stated goal was to be as forgiving as possible when running code, so that fast edit-execute cycles support rapid prototyping. The language spec reflects that, by making many errors only fire at runtime, rather than at compile time, even if they are detected by the compiler. |
"fire at runtime" is totally fine – we just want at way to know that an isolate failed BECAUSE of bad syntax with the related info. |
To be clear, my ideal solution here would be: if a function with a syntax error is executed at runtime, it throws an exception (maybe a new |
I agree with Natalie - if an Isolate starts running, it should keep running and should not be torn down in the middle of executing because it calls a function that has a previously undiscovered syntax error. |
Is there any update on this? We are currently running into the same issue with our continuous test runner for dart. If the test scheduled to run contains a syntax error, there is no way to detect that. |
Update just to say that this is important for browser-based tests. Right now we use timeouts, which is very brittle and not guaranteed to work well in every case. |
@sanfordredlich browser programs (once compiled to JavaScript) should not exhibit that problem. Obviously, if you are running your tests in Dartium, then you will be affected by this too. |
Thanks, yes, our tests will run in Dartium until Q4 or beyond. |
If I'm reading this right, the concern is that the compile-time behavior/error emitted by dart2js is different than the new runtime behavior of the VM? I consider this very much NOT an issue – we are introducing a very useful, but very VM-specific behavior IMHO. We want to keep a very VM-specific feature – lazy parsing – which is very different than what we do in dart2js. We just want it to do something more helpful than it does now. |
There are a slew of co19 tests which fail when we enable this feature because the co19 tests have a catch block which does nothing, yet the tests are expected to fail with a compilation error. One could say that the co19 test status files could be patched and the failing tests could be ignored, that is not a right thing to do. These tests need to be modified so that they continue to test the compilation errors that they were written to test. I would think a consistent behavior of the tools (dart2js and the VM runtime) is necessary in order for the co19 folks to get this right, otherwise you end up with one set of tests written explicitly for the way dart2js works and another for the way the runtime VM works making it more complex. |
I would also like to be able to catch syntax errors in Dartium. One thing I don't understand in the discussion on this issue: We can already catch syntax errors in the stand-alone Dart VM outside of Dartium reasonably well (package:test demonstrates that here for example). Why can the same functionality not be brought to Dartium? Personally, I find this difference between executing dart code in the stand-alone dart vm and executing dart code in Dartium very strange. |
Dartium implements something called DOM Isolates which are different from the stand-alone VM isolates and I don't believe these isolates were wired to implement the new Isolate API (ability to add an error listener) and treat errors as non Fatal which your test uses. Maybe @terrylucas can comment on whether this could be done in Dartium if that is all you need. |
Any update on this? The number 1 complained from the users of our continuous web test runner is that the runner cannot recover from syntax errors due to this issue. We simply cannot detect that there are syntax errors in the test file we are trying to run in Dartium. |
We've agreed to do this. We're discussing implementation details at the moment. Stay tuned... |
Pending CL: https://codereview.chromium.org/2044753002/ |
Exciting. Thanks for working on it. |
This issue is blocked on dart-lang/co19#69 |
Trying to figure out what the next steps are with dart-lang/co19#69 so we can get this landed... |
Bumping this to 1.20, while we are close we are not quite there |
dart-lang/co19#69 landed! @mhausner anything else you need to be unblocked? |
The co19 changes must be integrated into the sdk repo, if they aren't already. |
@whesse did you look at doing that integration? |
That is the co19 roll I did today and rolled back. With the status updates from this commit, I can land it permanently tomorrow. |
If an error happens during the compilation of a function body, an Error is thrown which can be intercepted, and ensures that finally blocks are executed before the isolate is terminated. The language spec is vague about compilation errors. A doc describing the intentions behind this CL is at https://docs.google.com/document/d/1_MWOgwJadLCQSBps0zD6Rj5dG4iP1UBuiDvTMH-WMzI/edit# Example: 1 void bad() { 2 return 5 3 } 4 5 void main(args) { 6 bad(); 7 } Before this CL: $ dart ~/tmp/e.dart 'file:///Users/hausner/tmp/e.dart': error: line 2 pos 11: semicolon expected return 5 ^ $ After this change: $ dart ~/tmp/e.dart Unhandled exception: 'file:///Users/hausner/tmp/e.dart': error: line 2 pos 11: semicolon expected return 5 ^ #0 main (file:///Users/hausner/tmp/e.dart:6:3) #1 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:259) #2 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:148) $ Notice that the stack trace points to the call site of bad(), not the text location of the syntax error. That's not a bug. The location of the syntax error is given in the error message. BUG= #23684 R=asiva@google.com, lrn@google.com Review URL: https://codereview.chromium.org/2044753002 .
Fixed in 3e0d13b – Woo hoo! Created a sample with pkg/test Before
After
I can see where the bad call happened. The rest of the tests ran. Awesome! |
Very cool! Thank you! Cannot wait to get my hands on it. |
Currently the following code throws an uncatchable syntax error:
This doesn't print "caught error", but instead kills the isolate due to the error. However, the error is only thrown at runtime, as can be seen with this modification:
This only throws a syntax error if an argument is passed on the command line. Moreover, the error is recoverable; for example:
Running
outer.dart
will produce two errors, so clearly there's a way to keep the isolate running and even keepbadFn
callable despite this syntax error.This is important for use cases like the test runner, where user code is loaded and specific functions are run. Error reporting should be associated with the functions that cause the errors, but they can only be captured globally and there's no way to link them back to the actual function that failed.
This also means that the user can't be confident that running an arbitrary function in an error zone will capture any errors that function might produce. This is useful even when not loading code dynamically; for example, an application may want to have a global error handler for itself that shows an error-reporting dialog.
The text was updated successfully, but these errors were encountered: