Skip to content

Commit

Permalink
Guard against reused fibers in React Native commands
Browse files Browse the repository at this point in the history
  • Loading branch information
yungsters committed Jul 8, 2021
1 parent 342d9db commit 1638ddc
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 23 deletions.
22 changes: 10 additions & 12 deletions packages/react-native-renderer/src/ReactFabric.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,16 +161,14 @@ function dispatchCommand(handle: any, command: string, args: Array<any>) {
'native component. Use React.forwardRef to get access to the underlying native component',
);
}

return;
}

if (handle._internalInstanceHandle) {
nativeFabricUIManager.dispatchCommand(
handle._internalInstanceHandle.stateNode.node,
command,
args,
);
if (handle._internalInstanceHandle != null) {
const {stateNode} = handle._internalInstanceHandle;
if (stateNode != null) {
nativeFabricUIManager.dispatchCommand(stateNode.node, command, args);
}
} else {
UIManager.dispatchViewManagerCommand(handle._nativeTag, command, args);
}
Expand All @@ -187,11 +185,11 @@ function sendAccessibilityEvent(handle: any, eventType: string) {
return;
}

if (handle._internalInstanceHandle) {
nativeFabricUIManager.sendAccessibilityEvent(
handle._internalInstanceHandle.stateNode.node,
eventType,
);
if (handle._internalInstanceHandle != null) {
const {stateNode} = handle._internalInstanceHandle;
if (stateNode != null) {
nativeFabricUIManager.sendAccessibilityEvent(stateNode.node, eventType);
}
} else {
legacySendAccessibilityEvent(handle._nativeTag, eventType);
}
Expand Down
21 changes: 10 additions & 11 deletions packages/react-native-renderer/src/ReactNativeRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,11 @@ function dispatchCommand(handle: any, command: string, args: Array<any>) {
return;
}

if (handle._internalInstanceHandle) {
nativeFabricUIManager.dispatchCommand(
handle._internalInstanceHandle.stateNode.node,
command,
args,
);
if (handle._internalInstanceHandle != null) {
const {stateNode} = handle._internalInstanceHandle;
if (stateNode != null) {
nativeFabricUIManager.dispatchCommand(stateNode.node, command, args);
}
} else {
UIManager.dispatchViewManagerCommand(handle._nativeTag, command, args);
}
Expand All @@ -183,11 +182,11 @@ function sendAccessibilityEvent(handle: any, eventType: string) {
return;
}

if (handle._internalInstanceHandle) {
nativeFabricUIManager.sendAccessibilityEvent(
handle._internalInstanceHandle.stateNode.node,
eventType,
);
if (handle._internalInstanceHandle != null) {
const {stateNode} = handle._internalInstanceHandle;
if (stateNode != null) {
nativeFabricUIManager.sendAccessibilityEvent(stateNode.node, eventType);
}
} else {
legacySendAccessibilityEvent(handle._nativeTag, eventType);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,38 @@ describe('ReactFabric', () => {
expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled();
});

it('should no-op if calling sendAccessibilityEvent on unmounted refs', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
uiViewClassName: 'RCTView',
}));

nativeFabricUIManager.sendAccessibilityEvent.mockReset();

let viewRef;
act(() => {
ReactFabric.render(
<View
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
});
const dangerouslyRetainedViewRef = viewRef;
act(() => {
ReactFabric.stopSurface(11);
});

ReactFabric.sendAccessibilityEvent(
dangerouslyRetainedViewRef,
'eventTypeName',
);

expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled();
});

it('should call FabricUIManager.measure on ref.measure', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand Down

0 comments on commit 1638ddc

Please sign in to comment.