-
Notifications
You must be signed in to change notification settings - Fork 47.5k
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
change the argument passed to CallbackQueue.getPooled #10101
Conversation
This code has not changed in a very long time, and doesn't seem to have changed between 15 and 16. Could you please:
Thanks! |
@gaearon ok, I think I mostly have it worked out. The code change that actually exposed this bug was in:
In version 15.4.1, you see this code:
The setState callbacks are getting pushed into that callbackQueue and run in that context. I can prove it by adding changing it to Since In version 16, all of that code is gone and the CallbackQueue is apparently being taken from the component or another intermediary instead. That's why when I made the change in my PR, it changed the callback function from being called with null to being called with undefined. I've created a unit test for ReactNativeReconcileTransaction but this is kind of a hard issue to test since testing the bug I actually experienced would involve unit tests on the React Native side of things. |
Can you rewrite the test to verify observable API instead of internals? In this particular case, you could write a test that schedules a This is important because the "transaction" code will be removed soon anyway. We want to ensure we doesn't regress on this behavior even if it's implemented in some different way. To force it to follow RN code path, you can do something like this. |
I replaced the test with one that tests setState directly with a mounted component. the format of the test is a bit odd. Originally, I had: it('calls setState with the correct parameters', () => {
var mockCallback = jest.fn();
class Component extends React.Component {
componentDidMount() {
this.setState({}, mockCallback);
}
render() {
return false;
}
}
ReactNative.render(<Component />, 11);
expect(mockCallback).toBeCalledWith(undefined);
}); That test worked as expected when I ran jest on it directly. But when I ran the I'm not sure what is causing the difference but this gets at the arguments with a closure rather than the jest mock functions so it should be a valid test |
Can you please run |
@@ -108,4 +108,20 @@ describe('ReactNative', () => { | |||
ReactNative.render(<Component chars={after} />, 11); | |||
expect(UIManager.__dumpHierarchyForJestTestsOnly()).toMatchSnapshot(); | |||
}); | |||
|
|||
it('calls setState with the correct parameters', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add a similar test to ReactTestUtils-test
for shallow renderer, and to ReactCompositeComponent-test
for DOM renderer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@gaearon I created those additional tests but to get them to pass, I had to fix another instance of that bug. It looks like that code is related to React for the web. I don't use React on the web so I can't easily verify if this was an issue |
I finally got prettier to run.
|
@gaearon Do I need to do anything else on this PR? Just want to make sure this isn't waiting on me to do something |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small changes.
@@ -844,4 +844,20 @@ describe('ReactTestUtils', () => { | |||
); | |||
}); | |||
}); | |||
|
|||
it('should call setState with the correct parameters', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's change this to should call setState callback with no arguments
(and others too)
|
||
it('should call setState with the correct parameters', () => { | ||
let mockArg = 'the wrong value'; | ||
let mockCallback = arg => (mockArg = arg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe let's assert arguments.length
is 0
instead of checking first argument?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so I tried this but npm test
causes the length of arguments to be 1, [ undefined ]
. But node ./scripts/fiber/record-tests
has the length of the arguments as 0, [ ]
So it seems like checking the first argument is the only way to go that I see
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you see where that undefined
comes from? I’d like to understand it.
Thanks for your work. This mostly looks good, just a few final comments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The extra argument is coming from here. Seems like CallbackQueue
assumes argument always exists. (cc @aweary, we introduced this arity issue in #7649)
But I don’t see us using this argument anymore. If you search for getPooled()
calls it’s always null
. The code that relied on it was deleted.
So let’s just completely remove _arg
from CallbackQueue
, stop passing it, and remove the argument to getPooled()
as well. Then you can fix up the tests to check arguments.length
too.
@gaearon ok, I removed |
This looks awesome. Thank you! This will get into React Native with the next sync. Note that this code doesn’t live in |
@gaearon thanks for all your feedback! |
fix to #10100