-
Notifications
You must be signed in to change notification settings - Fork 658
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
Many libraries can cause "Error.stack getter called with an invalid receiver" #1496
Comments
@thomasttvo hi, const MyError = function(message) {
this.message = message;
};
MyError.prototype = new Error;
MyError.prototype.name = 'MyError';
function foo() {
throw new MyError('1234')
}
function bar() {
foo();
}
try {
bar();
} catch (e) {
print(e.stack);
} If you run it with v8 or jsc, you get a useless stack trace:
So, why is this a useful? |
@tmikov Even though the error doesn't report the stack trace that points to where it is actually thrown, it's useful enough to find out which library it comes from. We have no control over what libraries do with their errors, some throw plain objects, some throw strings. In any of those cases, some info is good enough (When you run with v8, the stack actually points to the library where the error was initially defined), whereas the stack trace and data of |
@thomasttvo Do you have an explanation of what the point is of putting an Error object in the prototype? What does it accomplish? More importantly, is there a formal specification anywhere of how this should work? |
@tmikov I believe these libraries originated from a time pre-ES6 when class inheritance wasn't a feature. That was how Here's a non-error pre-es6 inheritance snippet from Bluebird Here's a custom error in handlebars.js What's worse, sometimes we may not even know we're using these libraries because they're dependencies of dependencies of dependencies |
@thomasttvo this is most definitely not how inheritance was implemented pre-ES6. At the very least it should call the parent constructor. |
We understand this is a real problem users of Hermes are having and we want to help. But we need to understand what the solution is. |
@tmikov you're right, that's not how you're supposed to do inheritance, but many extremely popular libraries use that method, and it didn't throw any error. I think the fix is to display the stack trace of the original error in the prototype and avoid throwing further errors when you perform operations on |
@thomasttvo yes, I think I am beginning to get the picture. One way or another we will make sure the |
thank you! with that said, if the stack getter returns |
Summary: Look for stack data in the entire prototype chain in order to accommodate usage like the one in the test. See facebook#1496 Differential Revision: D61870728
This is the fix, landing in Static Hermes. The getter returns the stack from the prototype. |
Summary: Pull Request resolved: facebook#1497 Look for stack data in the entire prototype chain in order to accommodate usage like the one in the test. See facebook#1496 Reviewed By: avp Differential Revision: D61870728
@tmikov looks like the fix was cancelled? |
I see, so it was just labeled "Closed" but it's merged? |
@wobsoriano yeah, I am not sure why it doesn't say "Merged", when it clearly was: ![]() |
Thanks @tmikov! and this is not yet available in the latest RN release right? |
Summary: Imported from static_h Original Author: [email protected] Original Git: 8b7a9f8 Original Reviewed By: avp Original Revision: D61870728 Look for stack data in the entire prototype chain in order to accommodate usage like the one in the test. See #1496 Reviewed By: fbmal7 Differential Revision: D62357838 fbshipit-source-id: 3873bfd8bcb5c16998dbec67f44ad4c098179758
@wobsoriano it will be in RN 0.76 |
…arent error manually to avoid Hermes from causing an error. See facebook/hermes#1496
I am on 0.76.6 and experiencing numerous of these errors in my production application. @tmikov can you please confirm this did indeed make it into 0.76? If yes then I will open another ticket to understand this issue further. |
@benjamin-sweney if you click on the commit, you can see the release tags it is in: db6d12e It is definitely in 0.76. |
We also see a significant increase in these errors using React Native 0.76.7 |
@exzos28 if you can provide a standalone reproduction, we will look into it. Also, please keep in mind that this pattern is objectively bad code, it isn't spec-compliant, and it should always be avoided in new code. But we do understand that old libraries relying on it exist. |
from mobx:
then:
and try to read:
|
@exzos28 thank you, I see the problem. We will fix it. Note that it doesn't "fatal" - it correctly throws an exception that the getter is applied to an incorrect target, namely an Object, when it should be applied to an instance of Error. |
@tmikov "fatal" - I meant it would crash the application. |
Sorry, I am not sure why a JS exception crashes the application. But it doesn't really matter. |
@tmikov My case is that I have an unhandled Next from sentry code:
and the application crashes with an error |
The fix is in: #1621 |
@thomasttvo turns out you were right, sorry! 😢 |
Bug Description
When an error is thrown while rendering, RN crashes of course as expected. However, for some errors, when
ExceptionsManager
callserror.stack
, it throws new errors, masking the original errors, which makes it impossible to know what the original error was for users in production (using tools like sentry).This happens when libraries using a technique like this to create their error classes:
I can find at least 5 popular libraries that use this technique, and if it works in classic JS, I think it's supposed to work with hermes?
React Native version: 0.73.5
OS: iOS, Android
Steps To Reproduce
The Expected Behavior
Calling
new MyError().stack
doesn't throwError.stack getter called with an invalid receiver
The text was updated successfully, but these errors were encountered: