Skip to content
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

[Fabric] Extract Fabric event handlers from canonical props #13024

Merged
merged 1 commit into from
Jun 13, 2018

Conversation

sebmarkbage
Copy link
Collaborator

We need a different "component tree" thingy for Fabric.

A lot of this doesn't really make much sense in a persistent world but
currently we can't dispatch events to memoizedProps on a Fiber since
they're pooled. Also, it's unclear what the semantics should be when we
dispatch an event that happened when the old props were in effect but now
we have new props already.

This implementation tries to use the last committed props but also fails
at that because we don't have a commit hook in the persistent mode.

However, at least it doesn't crash when dispatching. :)

@pull-bot
Copy link

pull-bot commented Jun 12, 2018

Details of bundled changes.

Comparing: 1594409...cb76d46

react-native-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactNativeRenderer-dev.js -0.0% -0.0% 457.81 KB 457.68 KB 100.07 KB 100.02 KB RN_FB_DEV
ReactNativeRenderer-prod.js 0.0% -0.0% 206.13 KB 206.14 KB 35.97 KB 35.97 KB RN_FB_PROD
ReactNativeRenderer-dev.js -0.0% -0.1% 457.47 KB 457.34 KB 100.01 KB 99.96 KB RN_OSS_DEV
ReactNativeRenderer-prod.js 0.0% -0.0% 194.12 KB 194.13 KB 33.94 KB 33.94 KB RN_OSS_PROD
ReactFabric-dev.js -0.2% -0.2% 448.73 KB 447.94 KB 97.84 KB 97.61 KB RN_FB_DEV
ReactFabric-prod.js -0.2% -0.3% 186.37 KB 186.03 KB 32.59 KB 32.5 KB RN_FB_PROD
ReactFabric-dev.js -0.2% -0.2% 448.76 KB 447.97 KB 97.85 KB 97.63 KB RN_OSS_DEV
ReactFabric-prod.js -0.2% -0.3% 186.4 KB 186.07 KB 32.61 KB 32.52 KB RN_OSS_PROD
ReactNativeRenderer-profiling.js 0.0% -0.0% 196.66 KB 196.66 KB 34.48 KB 34.48 KB RN_OSS_PROFILING
ReactFabric-profiling.js -0.2% -0.3% 188.62 KB 188.29 KB 33.07 KB 32.99 KB RN_OSS_PROFILING

Generated by 🚫 dangerJS

@sophiebits
Copy link
Collaborator

What’s the long term plan? I assume updating in render phase is not it?

@sebmarkbage
Copy link
Collaborator Author

I wasn’t actually sure what semantics made the most sense. However I spent tonight thinking about it and I think the only way imperative callbacks make sense is on a single timeline.

Even if they’re scheduled on different threads and different default priorities.

That means that if we have two async events like A and B that gets dispatched to the background thread.

But C is sync on the main thread, takes the lock, it can execute in between them.

So the timeline looks like A -> C -> B.

Then it is as if B happened after C. Which is weird because C might have changed the responder or something which would’ve made B impossible to fire.

But as far as JS is concerned, the sequence was A -> C -> B.

So if C updated some state, that should be available to the callback fired in B.

That seems to indicate that we want “last committed props” semantics. One way to achieve that is adding a commit phase hook which is how we do events in the mutable mode too.

Assuming A and B are serial events, they should always be guaranteed to fully flush before invoking the next serial event. So B always sees the changes of A, but the interesting scenario is when some sync work happens between the event happening on the main thread and it actually firing on the background thread.

Another possible semantic is that in that scenario we force the event to happen, eg on the main thread before invoking the sync event. But don’t actually render the result. That way there is never a conflict in imperative code.

We need a different "component tree" thingy for Fabric.

A lot of this doesn't really make much sense in a persistent world but
currently we can't dispatch events to memoizedProps on a Fiber since
they're pooled. Also, it's unclear what the semantics should be when we
dispatch an event that happened when the old props were in effect but now
we have new props already.

This implementation tries to use the last committed props but also fails
at that because we don't have a commit hook in the persistent mode.

However, at least it doesn't crash when dispatching. :)
@@ -293,6 +293,8 @@ export function prepareUpdate(
);
// TODO: If the event handlers have changed, we need to update the current props
// in the commit phase but there is no host config hook to do it yet.
// So instead we hack it by updating it in the render phase.
instance.canonical.currentProps = newProps;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is sufficient to fix the crashes? How important is the follow-up PR to add a commit phase hook?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't matter for sync mode but will be important eventually.

I'm considering using the memoizedProps solution to avoid having to add a commit phase in JS. Currently the commit phase is entire in native.

@sebmarkbage sebmarkbage merged commit 051637d into facebook:master Jun 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants