Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions Libraries/Animated/useAnimatedProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

'use strict';

import {isPublicInstance as isFabricPublicInstance} from '../Renderer/public/ReactFabricPublicInstance';
import useRefEffect from '../Utilities/useRefEffect';
import {AnimatedEvent} from './AnimatedEvent';
import NativeAnimatedHelper from './NativeAnimatedHelper';
Expand Down Expand Up @@ -183,7 +184,7 @@ function getEventTarget<TInstance>(instance: TInstance): TInstance {
// $FlowFixMe[unclear-type] - Legacy instance assumptions.
function isFabricInstance(instance: any): boolean {
return (
hasFabricHandle(instance) ||
isFabricPublicInstance(instance) ||
// Some components have a setNativeProps function but aren't a host component
// such as lists like FlatList and SectionList. These should also use
// forceUpdate in Fabric since setNativeProps doesn't exist on the underlying
Expand All @@ -192,13 +193,9 @@ function isFabricInstance(instance: any): boolean {
// If these components end up using forwardRef then these hacks can go away
// as instance would actually be the underlying host component and the above check
// would be sufficient.
hasFabricHandle(instance?.getNativeScrollRef?.()) ||
hasFabricHandle(instance?.getScrollResponder?.()?.getNativeScrollRef?.())
isFabricPublicInstance(instance?.getNativeScrollRef?.()) ||
isFabricPublicInstance(
instance?.getScrollResponder?.()?.getNativeScrollRef?.(),
)
);
}

// $FlowFixMe[unclear-type] - Legacy instance assumptions.
function hasFabricHandle(instance: any): boolean {
// eslint-disable-next-line dot-notation
return instance?.['_internalInstanceHandle']?.stateNode?.canonical != null;
}
6 changes: 2 additions & 4 deletions Libraries/Components/ScrollView/ScrollViewStickyHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import type {LayoutEvent} from '../../Types/CoreEventTypes';

import Animated from '../../Animated/Animated';
import {isPublicInstance as isFabricPublicInstance} from '../../Renderer/public/ReactFabricPublicInstance';
import StyleSheet from '../../StyleSheet/StyleSheet';
import Platform from '../../Utilities/Platform';
import useMergeRefs from '../../Utilities/useMergeRefs';
Expand Down Expand Up @@ -64,10 +65,7 @@ const ScrollViewStickyHeaderWithForwardedRef: React.AbstractComponent<
ref.setNextHeaderY = value => {
setNextHeaderLayoutY(value);
};
// Avoid dot notation because at Meta, private properties are obfuscated.
// $FlowFixMe[prop-missing]
const _internalInstanceHandler = ref['_internalInstanceHandle']; // eslint-disable-line dot-notation
setIsFabric(Boolean(_internalInstanceHandler?.stateNode?.canonical));
setIsFabric(isFabricPublicInstance(ref));
};
const ref: (React.ElementRef<typeof Animated.View> | null) => void =
// $FlowFixMe[incompatible-type] - Ref is mutated by `callbackRef`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ interface Agent {
}

type TraceNode = {
publicInstance?: TraceNode,
// TODO: remove this field when syncing the new version of the renderer from React to React Native.
canonical?: TraceNode,
measure?: (
(
Expand Down Expand Up @@ -100,7 +102,11 @@ export default function TraceUpdateOverlay(): React.Node {

const newFramesToDraw: Array<Promise<Overlay>> = [];
nodesToDraw.forEach(({node, color}) => {
const component = node.canonical ?? node;
// `publicInstance` => Fabric
// TODO: remove this check when syncing the new version of the renderer from React to React Native.
// `canonical` => Legacy Fabric
// `node` => Legacy renderer
const component = node.publicInstance ?? node.canonical ?? node;
if (!component || !component.measure) {
return;
}
Expand Down
8 changes: 6 additions & 2 deletions Libraries/Inspector/DevtoolsOverlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,12 @@ export default function DevtoolsOverlay({

function onAgentShowNativeHighlight(node: any) {
clearTimeout(hideTimeoutId);
// Shape of `node` is different in Fabric.
const component = node.canonical ?? node;

// `publicInstance` => Fabric
// TODO: remove this check when syncing the new version of the renderer from React to React Native.
// `canonical` => Legacy Fabric
// `node` => Legacy renderer
const component = node.publicInstance ?? node.canonical ?? node;
if (!component || !component.measure) {
return;
}
Expand Down
8 changes: 3 additions & 5 deletions Libraries/ReactNative/FabricUIManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @flow strict
* @format
*/

Expand All @@ -19,7 +19,7 @@ import type {
import type {RootTag} from '../Types/RootTagTypes';

// TODO: type these properly.
type Node = {...};
export opaque type Node = {...};
type NodeSet = Array<Node>;
type NodeProps = {...};
type InstanceHandle = {...};
Expand Down Expand Up @@ -53,9 +53,7 @@ export type Spec = {|
+configureNextLayoutAnimation: (
config: LayoutAnimationConfig,
callback: () => void, // check what is returned here
// This error isn't currently called anywhere, so the `error` object is really not defined
// $FlowFixMe[unclear-type]
errorCallback: (error: Object) => void,
errorCallback: () => void,
) => void,
+sendAccessibilityEvent: (node: Node, eventType: string) => void,
+findShadowNodeByTag_DEPRECATED: (reactTag: number) => ?Node,
Expand Down
30 changes: 30 additions & 0 deletions Libraries/Renderer/public/ReactFabricPublicInstance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict
*/

export function isPublicInstance(maybeInstance: mixed): boolean {
return (
maybeInstance != null &&
// TODO: implement a better check (maybe using instanceof) when the instance is defined in the React Native repository.
(maybeInstance.__nativeTag != null ||
// TODO: remove this check when syncing the new version of the renderer from React to React Native.
isLegacyFabricInstance(maybeInstance))
);
}

function isLegacyFabricInstance(maybeInstance: mixed): boolean {
/* eslint-disable dot-notation */
return (
maybeInstance != null &&
// $FlowExpectedError[incompatible-use]
maybeInstance['_internalInstanceHandle'] != null &&
maybeInstance['_internalInstanceHandle'].stateNode != null &&
maybeInstance['_internalInstanceHandle'].stateNode.canonical != null
);
}