-
-
Notifications
You must be signed in to change notification settings - Fork 80
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
"Uncaught JavaError in function callback" needs more details #446
Comments
Please leave a repo with the issue you mentioned and specify the expected behavior you want. |
Here you go |
That feature hasn't been implemented yet. It seems there are a few Javet users asking for this feature. I'll consider putting it in the future releases. |
Thanks. The augmented stacktrace should also be passed back to the outermost Java frame too (here This is an important feature, because debugging is very difficult without it. This should work for uncaught |
It might not be the one you wished. The feature I was thinking of is to carry over the Java stack trace as a JS string. Anything beyond that has already been resolved by other approaches. For instance:
A lot of Javet users are using this approach. Why doesn't Javet build it in? Because there are many things to be customized here. Javet leaves the freedom to the Javet users.
Please let me know if you have any questions. |
A user should not have to catch all exceptions, anywhere they could be thrown, just to be able to see what went wrong when something unexpected goes wrong. In Java, most exceptions are checked exceptions, so try-catch is used wherever exceptions are expected, and unchecked exceptions are only used for things that really are never supposed to happen, and when they do happen, it's serious. In Javascript, there are no checked exceptions whatsoever, so the chance of an exception being thrown that you didn't expect is very high. For this very reason, it is important to preserve all stack traces in code that runs in Javascript AND code that is run by Javascript. The user simply cannot be expected to surround every operation with try/catch. And even if they do use try/catch in Javascript, this is not "resolved by other approaches" to use your word, because the JS stack trace will not show the Java stack trace, if an exception is thrown in Java. Saving and re-throwing the exception doesn't preserve information that is not there. The caller of V8 needs to catch Javet exceptions. But those exceptions won't have the information the caller needs, if an exception is thrown in Java code run by V8.
Nothing I have proposed precludes a user from still doing those things. I am not talking about changing how or where exceptions are caught, or how they are handled. I am ONLY saying that exceptions need to include all information about ALL stack frames, in both JS and Java, regardless of where the exception is caught, or how it is handled. This is a major usability issue for Javet, in my opinion, so I don't know why you don't want to make this work end-to-end. I don't know the internals of Javet, but I don't see why this would be difficult or impossible to implement. BTW as far as I understand it, you can do better than just adding the Java stacktrace as part of the JS error message, by using |
Things are not as simple as you thought. V8 value cannot hold Java objects in V8, otherwise memory leak will happen. All API that imply multiple steps of inter-operation between JS and Java objects will cause potential memory leak, because step 2, 3, ...etc. may not happen. The simple solution is to convert the Java objects to native V8 values. |
You can just read the stack frames in Java, turn them into a stringified JSON object, and send a single string back to V8. And actually you could use V8's own stack frame JSON schema for this, so you can just plug the returned JSON straight into the V8 structured stack frame array. |
Actually, correction: you would need to wrap these structured JSON stack frames with a |
That won't be feasible for the following reasons.
You can always embed the stack trace in the error message by your custom exception implementation. The message can be in Json, XML, whatever format you want. |
The only types that need to be passed from a Java function that threw an exception back to JS are strings (filename, function name, type name of
Literally every single time an If you have caught a Java exception, the entire stack trace has already been obtained and stored (in fact it was created even before
What about the (I would claim very common) usecase where the Javet user wrote both the JS code, and the Java code it is calling? If you're calling custom Java functions from JS, then probably you wrote the JS code. Therefore, there are no security concerns in this case, and having a hobbled Javet, with no ability to get Javet to "do the right thing" and show all stack frames on exceptions, is a major usability issue. Now I am definitely a fan of security by default. So if you want to make Javet not create hybrid stacktraces by default, then that's fine -- but please add a switch to enable hybrid stacktraces in |
Thank you for sharing your thoughts.
|
You don't need to pass the entire It would be highly unusual for someone to extend You would meet 99.999% of the need (specifically the very common need of debugging) by providing only stacktrace info, not the full exception object.
Java programmers should know that exception production is expensive, and if they dig a little, they will discover they can make exceptions really fast by overriding But again, we are talking about providing debug info in the case of unexpected exceptions specifically, which (1) should be a rare event, and/or (2) should only happen during code development (therefore speed is not an issue, because the programmer cares far more about correctness and completeness than speed, at least initially), and/or (3) if an unexpected exception is thrown, it should be a showstopper since the exception is not caught anywhere (so who cares about overhead? It's a showstopper).
Well then I suggest making the generation of full stack trace the only behavior, and then telling Java users who call from their code into untrusted JS code, and then back into their own code, that if they care about security and don't want to expose any internals of their nested Java code to JS, they need to ensure they never throw an exception back to JS. This is a totally fair and reasonable thing for extremely security-conscious people to have to do anyway, EVEN if they never leave the Java world (e.g. their Java code calls an untrusted library, providing a callback to that library, which calls one of the user's own functions). In other words, your security concerns have nothing whatsoever to do with the fact that JS is inserted between Java and Java; it has to do with trusted code calling untrusted code, which calls user-supplied trusted code again that has to not expose its inner workings to the untrusted code. |
I have been always talking about general needs from various product requirements' perspective. I'm under the impression that you are focused on your need. Thus, I wonder the discussion wouldn't be fruitful if we are constantly in the separate channels. |
No, literally every argument I have made has been along the lines of "here is what the most likely usecase is" or "here is what programmers are most likely to expect". |
Edge cases are also critical to a framework / SDK developers. Most of use cases don't need the stack trace, and don't have to take the performance overhead. If you are not aware of those use cases, please browse other issues to get some ideas. They just need a way to stop the execution as quickly as possible. You custom needs can be achieved by yourself, but not suitable to be built in to the SDK. |
I don't understand -- you are saying it is important for a framework like Javet to handle edge cases, and then you are asking me to handle my own edge cases? And yet I don't believe that the needs I am describing are edge cases at all. I am talking about basic debugging functionality that EVERY developer will need at some point, until they have a fully running system, where, sure, maybe they won't want to take a performance hit for exceptions. During debugging, you NEED the information about what went wrong when something went wrong. It is fine if you don't enable this by default, but why do you not want to add an option to pass back at least source files and line numbers on exception? And no, I can't implement this functionality myself, because when an exception is thrown, I need to pass back the stack trace of the exception from the Java function that threw the exception, and if the return type is say There is literally no way at all to handle this, other than Javet adding support for developers to see the source of exceptions when they happen. |
You can pass anything via error message in arbitrary format.
You can do that. Most of use cases don't need to debug at all. They just want to terminate the script execution as soon as possible. |
The whole reason I filed this issue in the first place is that Javet shows no information whatsoever about Java exceptions in the stacktrace, only |
That's because the message of that Java exception is null. As I emphasized, you need to create your own exception with arbitrary message format to satisfy your requirements. |
As the test project I created shows, I threw a custom exception with a non-null message. It is wrapped in an |
I wonder what makes it so hard to write a PoC with a custom exception. |
No need to be so patronizing. Obviously throwing a custom exception is not hard. But that is not the solution I am asking for, because having to proactively wrap ALL code just in case an unchecked exception is thrown is not a solution. Honestly that is a ridiculous thing to require of your users. I don't know why you are resisting so hard helping your users to actually see what went wrong when unexpected things go wrong. This is NOT just about my specific use case. It's about a fundamental flaw in the functioning of Javet. The amount of code required for this will not be large. Please just put it behind a config switch, if you are so concerned about overhead. |
Please post your PoC and you will find there are numerous ways of customizations.
Those customizations cannot be built into Javet. Please do it by yourself. Other Javet users don't have to pay the performance penalty. Even a flag / enum in the config will slow down the script execution because many other users use exceptions as a cheap way of communication between JVM and V8. |
When I call into a Java method from V8, if the Java code triggers an
ExceptionInInitializerError
, then the JS code throwsUncaught JavaError in function callback
. However, no other information is provided back to V8, which means you have to single-step through the Java code to figure out what went wrong (and forExceptionInInitializerError
, it's not even easy to find the problem by single-stepping). There needs to be more info passed back to JS.Can you please include the
message
andException
/Error
class name from any JavaThrowable
in the JS exception'smessage
?Even better, can you please return the Java stacktrace as part of the stacktrace that is included when the JS exception is thrown? (I assume that it's possible to manually add things to a JS stacktrace, but I have no idea...)
The text was updated successfully, but these errors were encountered: