@samitouri / QOS-React / commits / 56922cf751

[react-native-renderer] Delete Paper (legacy) renderer (#36285)

## Summary The Paper renderer is no longer used in React Native. This commit removes all remaining Paper source code, tests, build system references, and Paper backward-compatibility branches in shared code. Deleted Paper-only source files: - ReactNativeRenderer.js, ReactNativeInjection.js, ReactFiberConfigNative.js - ReactNativeComponentTree.js, ReactNativeEventEmitter.js - ReactNativeFiberHostComponent.js, ReactNativeGlobalResponderHandler.js - ReactNativeAttributePayload.js, NativeMethodsMixinUtils.js - ReactFiberConfig.native.js (reconciler fork) - index.js (Paper entry point) Cleaned up shared files: - ReactNativePublicCompat.js: removed _nativeTag checks, UIManager/ legacySendAccessibilityEvent Paper fallbacks - ReactNativeFiberInspector.js: removed getInspectorDataForViewTag, UIManager.measure fallback, Paper branch in getInspectorDataForViewAtPoint - ReactFiberConfigFabric.js: removed _nativeTag backward compat in getPublicInstance, removed getInspectorDataForViewTag from devtools config - ReactNativeTypes.js: removed ReactNativeType (Paper API type) Cleaned up build system: - inlinedHostConfigs.js: removed shortName 'native' config - forks.js: removed dead 'react-native-renderer' case - Deleted ReactNative.js shim and Paper-only test mocks ## How did you test this change? Manually synced the renderer to RN and passed all Fantom tests. Manually verified the differences in the generated `ReactFabric-dev.js` file. Only Paper compat logic has been removed. <details> <summary>diff</summary> ```diff --- /tmp/react-fabric-baseline/ReactFabric-dev.js 2026-04-16 16:42:42 +++ build/react-native/implementations/ReactFabric-dev.js 2026-04-16 18:08:43 @@ -30,43 +30,19 @@ : emptyObject; } function createHierarchy(fiberHierarchy) { - return fiberHierarchy.map(function (fiber$jscomp$0) { + return fiberHierarchy.map(function (fiber) { return { - name: getComponentNameFromType(fiber$jscomp$0.type), + name: getComponentNameFromType(fiber.type), getInspectorData: function () { return { - props: getHostProps(fiber$jscomp$0), + props: getHostProps(fiber), measure: function (callback) { - var hostFiber = findCurrentHostFiber(fiber$jscomp$0); - if ( - (hostFiber = - null != hostFiber && - null !== hostFiber.stateNode && - hostFiber.stateNode.node) - ) + var hostFiber = findCurrentHostFiber(fiber); + (hostFiber = + null != hostFiber && + null !== hostFiber.stateNode && + hostFiber.stateNode.node) && nativeFabricUIManager.measure(hostFiber, callback); - else { - hostFiber = ReactNativePrivateInterface.UIManager; - var JSCompiler_temp_const = hostFiber.measure, - JSCompiler_inline_result; - a: { - for (var fiber = fiber$jscomp$0; fiber; ) { - null !== fiber.stateNode && - 5 === fiber.tag && - (JSCompiler_inline_result = findNodeHandle( - fiber.stateNode - )); - if (JSCompiler_inline_result) break a; - fiber = fiber.child; - } - JSCompiler_inline_result = null; - } - return JSCompiler_temp_const.call( - hostFiber, - JSCompiler_inline_result, - callback - ); - } } }; } @@ -1805,18 +1781,6 @@ } return null; } - function doesFiberContain(parentFiber, childFiber) { - for ( - var parentFiberAlternate = parentFiber.alternate; - null !== childFiber; - - ) { - if (childFiber === parentFiber || childFiber === parentFiberAlternate) - return !0; - childFiber = childFiber.return; - } - return !1; - } function traverseVisibleHostChildren( child, searchWithinHosts, @@ -16986,44 +16950,6 @@ function getCurrentFiberForDevTools() { return current; } - function findNodeHandle(componentOrHandle) { - var owner = current; - null !== owner && - isRendering && - null !== owner.stateNode && - (owner.stateNode._warnedAboutRefsInRender || - console.error( - "%s is accessing findNodeHandle inside its render(). render() should be a pure function of props and state. It should never access something that requires stale data from the previous render, such as refs. Move this logic to componentDidMount and componentDidUpdate instead.", - getComponentNameFromType(owner.type) || "A component" - ), - (owner.stateNode._warnedAboutRefsInRender = !0)); - if (null == componentOrHandle) return null; - if ("number" === typeof componentOrHandle) return componentOrHandle; - if (componentOrHandle._nativeTag) return componentOrHandle._nativeTag; - if ( - null != componentOrHandle.canonical && - null != componentOrHandle.canonical.nativeTag - ) - return componentOrHandle.canonical.nativeTag; - if ( - (owner = - ReactNativePrivateInterface.getNativeTagFromPublicInstance( - componentOrHandle - )) - ) - return owner; - componentOrHandle = findHostInstanceWithWarning( - componentOrHandle, - "findNodeHandle" - ); - return null == componentOrHandle - ? componentOrHandle - : null != componentOrHandle._nativeTag - ? componentOrHandle._nativeTag - : ReactNativePrivateInterface.getNativeTagFromPublicInstance( - componentOrHandle - ); - } function getNodeFromInternalInstanceHandle(internalInstanceHandle) { return ( internalInstanceHandle && @@ -17134,12 +17060,9 @@ } return instance.canonical.publicInstance; } - return null != instance.containerInfo && - null != instance.containerInfo.publicInstance + return null != instance.containerInfo ? instance.containerInfo.publicInstance - : null != instance._nativeTag - ? instance - : null; + : null; } function getPublicInstanceFromHostFiber(fiber) { fiber = getPublicInstance(fiber.stateNode); @@ -18017,7 +17940,6 @@ DefaultEventPriority = 32, IdleEventPriority = 268435456, searchTarget = null, - instanceCache = new Map(), bind = Function.prototype.bind, valueStack = []; var fiberStack = []; @@ -20041,24 +19963,19 @@ _nativeFabricUIManage.unstable_getCurrentEventPriority, extraDevToolsConfig = { getInspectorDataForInstance: getInspectorDataForInstance, - getInspectorDataForViewTag: function (viewTag) { - viewTag = instanceCache.get(viewTag) || null; - return getInspectorDataForInstance(viewTag); - }, getInspectorDataForViewAtPoint: function ( inspectedView, locationX, locationY, callback ) { - var closestInstance = null, - fabricNode = - ReactNativePrivateInterface.getNodeFromPublicInstance( - inspectedView - ); - fabricNode + var closestInstance = null; + (inspectedView = + ReactNativePrivateInterface.getNodeFromPublicInstance( + inspectedView + )) ? nativeFabricUIManager.findNodeAtPoint( - fabricNode, + inspectedView, locationX, locationY, function (internalInstanceHandle) { @@ -20109,32 +20026,9 @@ } } ) - : null != inspectedView._internalFiberInstanceHandleDEV - ? ReactNativePrivateInterface.UIManager.findSubviewIn( - findNodeHandle(inspectedView), - [locationX, locationY], - function (nativeViewTag, left, top, width, height) { - var inspectorData = getInspectorDataForInstance( - instanceCache.get(nativeViewTag) || null - ); - callback( - assign({}, inspectorData, { - pointerY: locationY, - frame: { - left: left, - top: top, - width: width, - height: height - }, - touchedViewTag: nativeViewTag, - closestPublicInstance: nativeViewTag - }) - ); - } - ) - : console.error( - "getInspectorDataForViewAtPoint expects to receive a host component" - ); + : console.error( + "getInspectorDataForViewAtPoint expects to receive a host component" + ); } }, getViewConfigForType = @@ -20368,23 +20262,12 @@ ); }; exports.dispatchCommand = function (handle, command, args) { - var nativeTag = - null != handle._nativeTag - ? handle._nativeTag - : ReactNativePrivateInterface.getNativeTagFromPublicInstance(handle); - null == nativeTag - ? console.error( + handle = ReactNativePrivateInterface.getNodeFromPublicInstance(handle); + null != handle + ? nativeFabricUIManager.dispatchCommand(handle, command, args) + : console.error( "dispatchCommand was called with a ref that isn't a native component. Use React.forwardRef to get access to the underlying native component" - ) - : ((handle = - ReactNativePrivateInterface.getNodeFromPublicInstance(handle)), - null != handle - ? nativeFabricUIManager.dispatchCommand(handle, command, args) - : ReactNativePrivateInterface.UIManager.dispatchViewManagerCommand( - nativeTag, - command, - args - )); + ); }; exports.findHostInstance_DEPRECATED = function (componentOrHandle) { var owner = current; @@ -20402,14 +20285,46 @@ : componentOrHandle.canonical && componentOrHandle.canonical.publicInstance ? componentOrHandle.canonical.publicInstance - : componentOrHandle._nativeTag - ? componentOrHandle - : findHostInstanceWithWarning( - componentOrHandle, - "findHostInstance_DEPRECATED" - ); + : findHostInstanceWithWarning( + componentOrHandle, + "findHostInstance_DEPRECATED" + ); }; - exports.findNodeHandle = findNodeHandle; + exports.findNodeHandle = function (componentOrHandle) { + var owner = current; + null !== owner && + isRendering && + null !== owner.stateNode && + (owner.stateNode._warnedAboutRefsInRender || + console.error( + "%s is accessing findNodeHandle inside its render(). render() should be a pure function of props and state. It should never access something that requires stale data from the previous render, such as refs. Move this logic to componentDidMount and componentDidUpdate instead.", + getComponentNameFromType(owner.type) || "A component" + ), + (owner.stateNode._warnedAboutRefsInRender = !0)); + if (null == componentOrHandle) return null; + if ("number" === typeof componentOrHandle) return componentOrHandle; + if ( + null != componentOrHandle.canonical && + null != componentOrHandle.canonical.nativeTag + ) + return componentOrHandle.canonical.nativeTag; + if ( + (owner = + ReactNativePrivateInterface.getNativeTagFromPublicInstance( + componentOrHandle + )) + ) + return owner; + componentOrHandle = findHostInstanceWithWarning( + componentOrHandle, + "findNodeHandle" + ); + return null == componentOrHandle + ? componentOrHandle + : ReactNativePrivateInterface.getNativeTagFromPublicInstance( + componentOrHandle + ); + }; exports.getNodeFromInternalInstanceHandle = getNodeFromInternalInstanceHandle; exports.getPublicInstanceFromInternalInstanceHandle = function ( @@ -20433,14 +20348,6 @@ : null; }; exports.isChildPublicInstance = function (parentInstance, childInstance) { - if ( - parentInstance._internalFiberInstanceHandleDEV && - childInstance._internalFiberInstanceHandleDEV - ) - return doesFiberContain( - parentInstance._internalFiberInstanceHandleDEV, - childInstance._internalFiberInstanceHandleDEV - ); parentInstance = ReactNativePrivateInterface.getInternalInstanceHandleFromPublicInstance( parentInstance @@ -20449,9 +20356,27 @@ ReactNativePrivateInterface.getInternalInstanceHandleFromPublicInstance( childInstance ); - return null != parentInstance && null != childInstance - ? doesFiberContain(parentInstance, childInstance) - : !1; + if (null != parentInstance && null != childInstance) { + a: { + for ( + var parentFiberAlternate = parentInstance.alternate; + null !== childInstance; + + ) { + if ( + childInstance === parentInstance || + childInstance === parentFiberAlternate + ) { + parentInstance = !0; + break a; + } + childInstance = childInstance.return; + } + parentInstance = !1; + } + return parentInstance; + } + return !1; }; exports.render = function ( element, @@ -20521,22 +20446,12 @@ return element; }; exports.sendAccessibilityEvent = function (handle, eventType) { - var nativeTag = - null != handle._nativeTag - ? handle._nativeTag - : ReactNativePrivateInterface.getNativeTagFromPublicInstance(handle); - null == nativeTag - ? console.error( + handle = ReactNativePrivateInterface.getNodeFromPublicInstance(handle); + null != handle + ? nativeFabricUIManager.sendAccessibilityEvent(handle, eventType) + : console.error( "sendAccessibilityEvent was called with a ref that isn't a native component. Use React.forwardRef to get access to the underlying native component" - ) - : ((handle = - ReactNativePrivateInterface.getNodeFromPublicInstance(handle)), - null != handle - ? nativeFabricUIManager.sendAccessibilityEvent(handle, eventType) - : ReactNativePrivateInterface.legacySendAccessibilityEvent( - nativeTag, - eventType - )); + ); }; exports.stopSurface = function (containerTag) { var root = roots.get(containerTag); ``` </details>

Rubén Norte committed Apr 16, 2026 at 18:34 UTC 56922cf751fab6c7ab4c12ddbbd15839959fa255
35 files changed +16 -4703
packages/react-native-renderer/index.js deleted
-16
@@ -1,16 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -import type {ReactNativeType} from './src/ReactNativeTypes';
11 -import * as ReactNative from './src/ReactNativeRenderer';
12 -// Assert that the exports line up with the type we're going to expose.
13 -(ReactNative: ReactNativeType);
14 -
15 -// TODO: Delete the legacy renderer, only Fabric is used now.
16 -export * from './src/ReactNativeRenderer';
packages/react-native-renderer/src/NativeMethodsMixinUtils.js deleted
-64
@@ -1,64 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -/**
11 - * In the future, we should cleanup callbacks by cancelling them instead of
12 - * using this.
13 - */
14 -export function mountSafeCallback_NOT_REALLY_SAFE(
15 - context: any,
16 - callback: ?Function,
17 -): any {
18 - return function () {
19 - if (!callback) {
20 - return undefined;
21 - }
22 - // This protects against createClass() components.
23 - // We don't know if there is code depending on it.
24 - // We intentionally don't use isMounted() because even accessing
25 - // isMounted property on a React ES6 class will trigger a warning.
26 - if (typeof context.__isMounted === 'boolean') {
27 - if (!context.__isMounted) {
28 - return undefined;
29 - }
30 - }
31 -
32 - // FIXME: there used to be other branches that protected
33 - // against unmounted host components. But RN host components don't
34 - // define isMounted() anymore, so those checks didn't do anything.
35 -
36 - // They caused false positive warning noise so we removed them:
37 - // https://github.com/facebook/react-native/issues/18868#issuecomment-413579095
38 -
39 - // However, this means that the callback is NOT guaranteed to be safe
40 - // for host components. The solution we should implement is to make
41 - // UIManager.measure() and similar calls truly cancelable. Then we
42 - // can change our own code calling them to cancel when something unmounts.
43 -
44 - return callback.apply(context, arguments);
45 - };
46 -}
47 -
48 -export function warnForStyleProps(props: any, validAttributes: any) {
49 - if (__DEV__) {
50 - for (const key in validAttributes.style) {
51 - if (!(validAttributes[key] || props[key] === undefined)) {
52 - console.error(
53 - 'You are setting the style `{ %s' +
54 - ': ... }` as a prop. You ' +
55 - 'should nest it in a style object. ' +
56 - 'E.g. `{ style: { %s' +
57 - ': ... } }`',
58 - key,
59 - key,
60 - );
61 - }
62 - }
63 - }
64 -}
packages/react-native-renderer/src/ReactFiberConfigFabric.js
+1 -15
@@ -66,7 +66,6 @@ import {getClosestInstanceFromNode} from './ReactFabricComponentTree';
66 import {compareDocumentPositionForEmptyFragment} from 'shared/ReactDOMFragmentRefShared';
67
68 import {
69 - getInspectorDataForViewTag,
69 getInspectorDataForViewAtPoint,
70 getInspectorDataForInstance,
71 } from './ReactNativeFiberInspector';
@@ -79,7 +78,6 @@ export {default as rendererVersion} from 'shared/ReactVersion'; // TODO: Conside
78 export const rendererPackageName = 'react-native-renderer';
79 export const extraDevToolsConfig = {
80 getInspectorDataForInstance,
82 - getInspectorDataForViewTag,
81 getInspectorDataForViewAtPoint,
82 };
83
@@ -142,8 +140,6 @@ export type TransitionStatus = mixed;
140
141 export type RendererInspectionConfig = $ReadOnly<{
142 getInspectorDataForInstance?: (instance: Fiber | null) => InspectorData,
145 - // Deprecated. Replaced with getInspectorDataForViewAtPoint.
146 - getInspectorDataForViewTag?: (tag: number) => Object,
143 getInspectorDataForViewAtPoint?: (
144 inspectedView: Object,
145 locationX: number,
@@ -313,17 +309,7 @@ export function getPublicInstance(instance: Instance): null | PublicInstance {
309
310 // Handle root containers
311 if (instance.containerInfo != null) {
316 - if (instance.containerInfo.publicInstance != null) {
317 - return instance.containerInfo.publicInstance;
318 - }
319 - }
320 -
321 - // For compatibility with the legacy renderer, in case it's used with Fabric
322 - // in the same app.
323 - // $FlowExpectedError[prop-missing]
324 - if (instance._nativeTag != null) {
325 - // $FlowExpectedError[incompatible-return]
326 - return instance;
312 + return instance.containerInfo.publicInstance;
313 }
314
315 return null;
packages/react-native-renderer/src/ReactFiberConfigNative.js deleted
-845
@@ -1,845 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -import type {InspectorData, TouchedViewDataAtPoint} from './ReactNativeTypes';
11 -import type {TransitionTypes} from 'react/src/ReactTransitionType';
12 -
13 -// Modules provided by RN:
14 -import {
15 - ReactNativeViewConfigRegistry,
16 - UIManager,
17 - deepFreezeAndThrowOnMutationInDev,
18 - createPublicInstance,
19 - type PublicRootInstance,
20 -} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
21 -
22 -import {create, diff} from './ReactNativeAttributePayload';
23 -import {
24 - precacheFiberNode,
25 - uncacheFiberNode,
26 - updateFiberProps,
27 - getClosestInstanceFromNode,
28 -} from './ReactNativeComponentTree';
29 -import ReactNativeFiberHostComponent from './ReactNativeFiberHostComponent';
30 -
31 -import {
32 - DefaultEventPriority,
33 - NoEventPriority,
34 - type EventPriority,
35 -} from 'react-reconciler/src/ReactEventPriorities';
36 -import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
37 -
38 -import {enableProfilerTimer} from 'shared/ReactFeatureFlags';
39 -
40 -import {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';
41 -import type {ReactContext} from 'shared/ReactTypes';
42 -
43 -import {
44 - getInspectorDataForViewTag,
45 - getInspectorDataForViewAtPoint,
46 - getInspectorDataForInstance,
47 -} from './ReactNativeFiberInspector';
48 -
49 -export {default as rendererVersion} from 'shared/ReactVersion'; // TODO: Consider exporting the react-native version.
50 -export const rendererPackageName = 'react-native-renderer';
51 -export const extraDevToolsConfig = {
52 - getInspectorDataForInstance,
53 - getInspectorDataForViewTag,
54 - getInspectorDataForViewAtPoint,
55 -};
56 -
57 -const {get: getViewConfigForType} = ReactNativeViewConfigRegistry;
58 -
59 -export type Type = string;
60 -export type Props = Object;
61 -export type Container = {
62 - containerTag: number,
63 - publicInstance: PublicRootInstance | null,
64 -};
65 -export type Instance = ReactNativeFiberHostComponent;
66 -export type TextInstance = number;
67 -export type HydratableInstance = Instance | TextInstance;
68 -export type PublicInstance = Instance;
69 -export type HostContext = $ReadOnly<{
70 - isInAParentText: boolean,
71 -}>;
72 -export type UpdatePayload = Object; // Unused
73 -export type ChildSet = void; // Unused
74 -
75 -export type TimeoutHandle = TimeoutID;
76 -export type NoTimeout = -1;
77 -export type TransitionStatus = mixed;
78 -
79 -export type RendererInspectionConfig = $ReadOnly<{
80 - getInspectorDataForInstance?: (instance: Fiber | null) => InspectorData,
81 - // Deprecated. Replaced with getInspectorDataForViewAtPoint.
82 - getInspectorDataForViewTag?: (tag: number) => Object,
83 - getInspectorDataForViewAtPoint?: (
84 - inspectedView: Object,
85 - locationX: number,
86 - locationY: number,
87 - callback: (viewData: TouchedViewDataAtPoint) => mixed,
88 - ) => void,
89 -}>;
90 -
91 -// Counter for uniquely identifying views.
92 -// % 10 === 1 means it is a rootTag.
93 -// % 2 === 0 means it is a Fabric tag.
94 -let nextReactTag = 3;
95 -function allocateTag() {
96 - let tag = nextReactTag;
97 - if (tag % 10 === 1) {
98 - tag += 2;
99 - }
100 - nextReactTag = tag + 2;
101 - return tag;
102 -}
103 -
104 -function recursivelyUncacheFiberNode(node: Instance | TextInstance) {
105 - if (typeof node === 'number') {
106 - // Leaf node (eg text)
107 - uncacheFiberNode(node);
108 - } else {
109 - uncacheFiberNode((node: any)._nativeTag);
110 -
111 - (node: any)._children.forEach(recursivelyUncacheFiberNode);
112 - }
113 -}
114 -
115 -export * from 'react-reconciler/src/ReactFiberConfigWithNoPersistence';
116 -export * from 'react-reconciler/src/ReactFiberConfigWithNoHydration';
117 -export * from 'react-reconciler/src/ReactFiberConfigWithNoScopes';
118 -export * from 'react-reconciler/src/ReactFiberConfigWithNoTestSelectors';
119 -export * from 'react-reconciler/src/ReactFiberConfigWithNoMicrotasks';
120 -export * from 'react-reconciler/src/ReactFiberConfigWithNoResources';
121 -export * from 'react-reconciler/src/ReactFiberConfigWithNoSingletons';
122 -
123 -export function appendInitialChild(
124 - parentInstance: Instance,
125 - child: Instance | TextInstance,
126 -): void {
127 - parentInstance._children.push(child);
128 -}
129 -
130 -export function createInstance(
131 - type: string,
132 - props: Props,
133 - rootContainerInstance: Container,
134 - hostContext: HostContext,
135 - internalInstanceHandle: Object,
136 -): Instance {
137 - const tag = allocateTag();
138 - const viewConfig = getViewConfigForType(type);
139 -
140 - if (__DEV__) {
141 - for (const key in viewConfig.validAttributes) {
142 - if (props.hasOwnProperty(key)) {
143 - deepFreezeAndThrowOnMutationInDev(props[key]);
144 - }
145 - }
146 - }
147 -
148 - const updatePayload = create(props, viewConfig.validAttributes);
149 -
150 - UIManager.createView(
151 - tag, // reactTag
152 - viewConfig.uiViewClassName, // viewName
153 - rootContainerInstance.containerTag, // rootTag
154 - updatePayload, // props
155 - );
156 -
157 - const component = new ReactNativeFiberHostComponent(
158 - tag,
159 - viewConfig,
160 - internalInstanceHandle,
161 - );
162 -
163 - precacheFiberNode(internalInstanceHandle, tag);
164 - updateFiberProps(tag, props);
165 -
166 - // Not sure how to avoid this cast. Flow is okay if the component is defined
167 - // in the same file but if it's external it can't see the types.
168 - return ((component: any): Instance);
169 -}
170 -
171 -export function cloneMutableInstance(
172 - instance: Instance,
173 - keepChildren: boolean,
174 -): Instance {
175 - throw new Error('Not yet implemented.');
176 -}
177 -
178 -export function createTextInstance(
179 - text: string,
180 - rootContainerInstance: Container,
181 - hostContext: HostContext,
182 - internalInstanceHandle: Object,
183 -): TextInstance {
184 - if (!hostContext.isInAParentText) {
185 - throw new Error('Text strings must be rendered within a <Text> component.');
186 - }
187 -
188 - const tag = allocateTag();
189 -
190 - UIManager.createView(
191 - tag, // reactTag
192 - 'RCTRawText', // viewName
193 - rootContainerInstance.containerTag, // rootTag
194 - {text: text}, // props
195 - );
196 -
197 - precacheFiberNode(internalInstanceHandle, tag);
198 -
199 - return tag;
200 -}
201 -
202 -export function cloneMutableTextInstance(
203 - textInstance: TextInstance,
204 -): TextInstance {
205 - throw new Error('Not yet implemented.');
206 -}
207 -
208 -export type FragmentInstanceType = null;
209 -
210 -export function createFragmentInstance(
211 - fragmentFiber: Fiber,
212 -): FragmentInstanceType {
213 - return null;
214 -}
215 -
216 -export function updateFragmentInstanceFiber(
217 - fragmentFiber: Fiber,
218 - instance: FragmentInstanceType,
219 -): void {
220 - // Noop
221 -}
222 -
223 -export function commitNewChildToFragmentInstance(
224 - child: PublicInstance,
225 - fragmentInstance: FragmentInstanceType,
226 -): void {
227 - // Noop
228 -}
229 -
230 -export function deleteChildFromFragmentInstance(
231 - child: PublicInstance,
232 - fragmentInstance: FragmentInstanceType,
233 -): void {
234 - // Noop
235 -}
236 -
237 -export function finalizeInitialChildren(
238 - parentInstance: Instance,
239 - type: string,
240 - props: Props,
241 - hostContext: HostContext,
242 -): boolean {
243 - // Don't send a no-op message over the bridge.
244 - if (parentInstance._children.length === 0) {
245 - return false;
246 - }
247 -
248 - // Map from child objects to native tags.
249 - // Either way we need to pass a copy of the Array to prevent it from being frozen.
250 - const nativeTags = parentInstance._children.map(child =>
251 - typeof child === 'number'
252 - ? child // Leaf node (eg text)
253 - : child._nativeTag,
254 - );
255 -
256 - UIManager.setChildren(
257 - parentInstance._nativeTag, // containerTag
258 - nativeTags, // reactTags
259 - );
260 -
261 - return false;
262 -}
263 -
264 -export function getRootHostContext(
265 - rootContainerInstance: Container,
266 -): HostContext {
267 - return {isInAParentText: false};
268 -}
269 -
270 -export function getChildHostContext(
271 - parentHostContext: HostContext,
272 - type: string,
273 -): HostContext {
274 - const prevIsInAParentText = parentHostContext.isInAParentText;
275 - const isInAParentText =
276 - type === 'AndroidTextInput' || // Android
277 - type === 'RCTMultilineTextInputView' || // iOS
278 - type === 'RCTSelectableText' ||
279 - type === 'RCTSinglelineTextInputView' || // iOS
280 - type === 'RCTText' ||
281 - type === 'RCTVirtualText';
282 -
283 - if (prevIsInAParentText !== isInAParentText) {
284 - return {isInAParentText};
285 - } else {
286 - return parentHostContext;
287 - }
288 -}
289 -
290 -export function getPublicInstance(instance: Instance): PublicInstance {
291 - // $FlowExpectedError[prop-missing] For compatibility with Fabric
292 - if (instance.canonical != null) {
293 - if (instance.canonical.publicInstance == null) {
294 - // $FlowExpectedError[incompatible-use]
295 - instance.canonical.publicInstance = createPublicInstance(
296 - // $FlowExpectedError[incompatible-use]
297 - instance.canonical.nativeTag,
298 - // $FlowExpectedError[incompatible-use]
299 - instance.canonical.viewConfig,
300 - // $FlowExpectedError[incompatible-use]
301 - instance.canonical.internalInstanceHandle,
302 - // $FlowExpectedError[incompatible-use]
303 - instance.canonical.publicRootInstance ?? null,
304 - );
305 - // This was only necessary to create the public instance.
306 - // $FlowExpectedError[prop-missing]
307 - instance.canonical.publicRootInstance = null;
308 - }
309 -
310 - // $FlowExpectedError[prop-missing]
311 - // $FlowExpectedError[incompatible-return]
312 - return instance.canonical.publicInstance;
313 - }
314 -
315 - return instance;
316 -}
317 -
318 -export function prepareForCommit(containerInfo: Container): null | Object {
319 - // Noop
320 - return null;
321 -}
322 -
323 -export function resetAfterCommit(containerInfo: Container): void {
324 - // Noop
325 -}
326 -
327 -export const isPrimaryRenderer = true;
328 -export const warnsIfNotActing = true;
329 -
330 -export const scheduleTimeout = setTimeout;
331 -export const cancelTimeout = clearTimeout;
332 -export const noTimeout: -1 = -1;
333 -
334 -export function shouldSetTextContent(type: string, props: Props): boolean {
335 - // TODO (bvaughn) Revisit this decision.
336 - // Always returning false simplifies the createInstance() implementation,
337 - // But creates an additional child Fiber for raw text children.
338 - // No additional native views are created though.
339 - // It's not clear to me which is better so I'm deferring for now.
340 - // More context @ github.com/facebook/react/pull/8560#discussion_r92111303
341 - return false;
342 -}
343 -
344 -let currentUpdatePriority: EventPriority = NoEventPriority;
345 -export function setCurrentUpdatePriority(newPriority: EventPriority): void {
346 - currentUpdatePriority = newPriority;
347 -}
348 -
349 -export function getCurrentUpdatePriority(): EventPriority {
350 - return currentUpdatePriority;
351 -}
352 -
353 -export function resolveUpdatePriority(): EventPriority {
354 - if (currentUpdatePriority !== NoEventPriority) {
355 - return currentUpdatePriority;
356 - }
357 - return DefaultEventPriority;
358 -}
359 -
360 -export function trackSchedulerEvent(): void {}
361 -
362 -export function resolveEventType(): null | string {
363 - return null;
364 -}
365 -
366 -export function resolveEventTimeStamp(): number {
367 - return -1.1;
368 -}
369 -
370 -export function shouldAttemptEagerTransition(): boolean {
371 - return false;
372 -}
373 -
374 -// -------------------
375 -// Mutation
376 -// -------------------
377 -
378 -export const supportsMutation = true;
379 -
380 -export function appendChild(
381 - parentInstance: Instance,
382 - child: Instance | TextInstance,
383 -): void {
384 - const childTag = typeof child === 'number' ? child : child._nativeTag;
385 - const children = parentInstance._children;
386 - const index = children.indexOf(child);
387 -
388 - if (index >= 0) {
389 - children.splice(index, 1);
390 - children.push(child);
391 -
392 - UIManager.manageChildren(
393 - parentInstance._nativeTag, // containerTag
394 - [index], // moveFromIndices
395 - [children.length - 1], // moveToIndices
396 - [], // addChildReactTags
397 - [], // addAtIndices
398 - [], // removeAtIndices
399 - );
400 - } else {
401 - children.push(child);
402 -
403 - UIManager.manageChildren(
404 - parentInstance._nativeTag, // containerTag
405 - [], // moveFromIndices
406 - [], // moveToIndices
407 - [childTag], // addChildReactTags
408 - [children.length - 1], // addAtIndices
409 - [], // removeAtIndices
410 - );
411 - }
412 -}
413 -
414 -export function appendChildToContainer(
415 - parentInstance: Container,
416 - child: Instance | TextInstance,
417 -): void {
418 - const childTag = typeof child === 'number' ? child : child._nativeTag;
419 - UIManager.setChildren(
420 - parentInstance.containerTag, // containerTag
421 - [childTag], // reactTags
422 - );
423 -}
424 -
425 -export function commitTextUpdate(
426 - textInstance: TextInstance,
427 - oldText: string,
428 - newText: string,
429 -): void {
430 - UIManager.updateView(
431 - textInstance, // reactTag
432 - 'RCTRawText', // viewName
433 - {text: newText}, // props
434 - );
435 -}
436 -
437 -export function commitMount(
438 - instance: Instance,
439 - type: string,
440 - newProps: Props,
441 - internalInstanceHandle: Object,
442 -): void {
443 - // Noop
444 -}
445 -
446 -export function commitUpdate(
447 - instance: Instance,
448 - type: string,
449 - oldProps: Props,
450 - newProps: Props,
451 - internalInstanceHandle: Object,
452 -): void {
453 - const viewConfig = instance.viewConfig;
454 -
455 - updateFiberProps(instance._nativeTag, newProps);
456 -
457 - const updatePayload = diff(oldProps, newProps, viewConfig.validAttributes);
458 -
459 - // Avoid the overhead of bridge calls if there's no update.
460 - // This is an expensive no-op for Android, and causes an unnecessary
461 - // view invalidation for certain components (eg RCTTextInput) on iOS.
462 - if (updatePayload != null) {
463 - UIManager.updateView(
464 - instance._nativeTag, // reactTag
465 - viewConfig.uiViewClassName, // viewName
466 - updatePayload, // props
467 - );
468 - }
469 -}
470 -
471 -export function insertBefore(
472 - parentInstance: Instance,
473 - child: Instance | TextInstance,
474 - beforeChild: Instance | TextInstance,
475 -): void {
476 - const children = (parentInstance: any)._children;
477 - const index = children.indexOf(child);
478 -
479 - // Move existing child or add new child?
480 - if (index >= 0) {
481 - children.splice(index, 1);
482 - const beforeChildIndex = children.indexOf(beforeChild);
483 - children.splice(beforeChildIndex, 0, child);
484 -
485 - UIManager.manageChildren(
486 - (parentInstance: any)._nativeTag, // containerID
487 - [index], // moveFromIndices
488 - [beforeChildIndex], // moveToIndices
489 - [], // addChildReactTags
490 - [], // addAtIndices
491 - [], // removeAtIndices
492 - );
493 - } else {
494 - const beforeChildIndex = children.indexOf(beforeChild);
495 - children.splice(beforeChildIndex, 0, child);
496 -
497 - const childTag = typeof child === 'number' ? child : child._nativeTag;
498 -
499 - UIManager.manageChildren(
500 - (parentInstance: any)._nativeTag, // containerID
501 - [], // moveFromIndices
502 - [], // moveToIndices
503 - [childTag], // addChildReactTags
504 - [beforeChildIndex], // addAtIndices
505 - [], // removeAtIndices
506 - );
507 - }
508 -}
509 -
510 -export function insertInContainerBefore(
511 - parentInstance: Container,
512 - child: Instance | TextInstance,
513 - beforeChild: Instance | TextInstance,
514 -): void {
515 - // TODO (bvaughn): Remove this check when...
516 - // We create a wrapper object for the container in ReactNative render()
517 - // Or we refactor to remove wrapper objects entirely.
518 - // For more info on pros/cons see PR #8560 description.
519 - if (typeof parentInstance === 'number') {
520 - throw new Error('Container does not support insertBefore operation');
521 - }
522 -}
523 -
524 -export function removeChild(
525 - parentInstance: Instance,
526 - child: Instance | TextInstance,
527 -): void {
528 - recursivelyUncacheFiberNode(child);
529 - const children = parentInstance._children;
530 - const index = children.indexOf(child);
531 -
532 - children.splice(index, 1);
533 -
534 - UIManager.manageChildren(
535 - parentInstance._nativeTag, // containerID
536 - [], // moveFromIndices
537 - [], // moveToIndices
538 - [], // addChildReactTags
539 - [], // addAtIndices
540 - [index], // removeAtIndices
541 - );
542 -}
543 -
544 -export function removeChildFromContainer(
545 - parentInstance: Container,
546 - child: Instance | TextInstance,
547 -): void {
548 - recursivelyUncacheFiberNode(child);
549 - UIManager.manageChildren(
550 - parentInstance.containerTag, // containerID
551 - [], // moveFromIndices
552 - [], // moveToIndices
553 - [], // addChildReactTags
554 - [], // addAtIndices
555 - [0], // removeAtIndices
556 - );
557 -}
558 -
559 -export function resetTextContent(instance: Instance): void {
560 - // Noop
561 -}
562 -
563 -export function hideInstance(instance: Instance): void {
564 - const viewConfig = instance.viewConfig;
565 - const updatePayload = create(
566 - {style: {display: 'none'}},
567 - viewConfig.validAttributes,
568 - );
569 - UIManager.updateView(
570 - instance._nativeTag,
571 - viewConfig.uiViewClassName,
572 - updatePayload,
573 - );
574 -}
575 -
576 -export function hideTextInstance(textInstance: TextInstance): void {
577 - throw new Error('Not yet implemented.');
578 -}
579 -
580 -export function unhideInstance(instance: Instance, props: Props): void {
581 - const viewConfig = instance.viewConfig;
582 - const updatePayload = diff(
583 - {...props, style: [props.style, {display: 'none'}]},
584 - props,
585 - viewConfig.validAttributes,
586 - );
587 - UIManager.updateView(
588 - instance._nativeTag,
589 - viewConfig.uiViewClassName,
590 - updatePayload,
591 - );
592 -}
593 -
594 -export function applyViewTransitionName(
595 - instance: Instance,
596 - name: string,
597 - className: ?string,
598 -): void {
599 - // Not yet implemented
600 -}
601 -
602 -export function restoreViewTransitionName(
603 - instance: Instance,
604 - props: Props,
605 -): void {
606 - // Not yet implemented
607 -}
608 -
609 -export function cancelViewTransitionName(
610 - instance: Instance,
611 - name: string,
612 - props: Props,
613 -): void {
614 - // Not yet implemented
615 -}
616 -
617 -export function cancelRootViewTransitionName(rootContainer: Container): void {
618 - // Not yet implemented
619 -}
620 -
621 -export function restoreRootViewTransitionName(rootContainer: Container): void {
622 - // Not yet implemented
623 -}
624 -
625 -export function cloneRootViewTransitionContainer(
626 - rootContainer: Container,
627 -): Instance {
628 - throw new Error('Not implemented.');
629 -}
630 -
631 -export function removeRootViewTransitionClone(
632 - rootContainer: Container,
633 - clone: Instance,
634 -): void {
635 - throw new Error('Not implemented.');
636 -}
637 -
638 -export type InstanceMeasurement = null;
639 -
640 -export function measureInstance(instance: Instance): InstanceMeasurement {
641 - // This heuristic is better implemented at the native layer.
642 - return null;
643 -}
644 -
645 -export function measureClonedInstance(instance: Instance): InstanceMeasurement {
646 - return null;
647 -}
648 -
649 -export function wasInstanceInViewport(
650 - measurement: InstanceMeasurement,
651 -): boolean {
652 - return true;
653 -}
654 -
655 -export function hasInstanceChanged(
656 - oldMeasurement: InstanceMeasurement,
657 - newMeasurement: InstanceMeasurement,
658 -): boolean {
659 - return false;
660 -}
661 -
662 -export function hasInstanceAffectedParent(
663 - oldMeasurement: InstanceMeasurement,
664 - newMeasurement: InstanceMeasurement,
665 -): boolean {
666 - return false;
667 -}
668 -
669 -export function startViewTransition(
670 - suspendedState: null | SuspendedState,
671 - rootContainer: Container,
672 - transitionTypes: null | TransitionTypes,
673 - mutationCallback: () => void,
674 - layoutCallback: () => void,
675 - afterMutationCallback: () => void,
676 - spawnedWorkCallback: () => void,
677 - passiveCallback: () => mixed,
678 - errorCallback: mixed => void,
679 - blockedCallback: string => void, // Profiling-only
680 - finishedAnimation: () => void, // Profiling-only
681 -): null | RunningViewTransition {
682 - mutationCallback();
683 - layoutCallback();
684 - // Skip afterMutationCallback(). We don't need it since we're not animating.
685 - spawnedWorkCallback();
686 - if (enableProfilerTimer) {
687 - finishedAnimation();
688 - }
689 - // Skip passiveCallback(). Spawned work will schedule a task.
690 - return null;
691 -}
692 -
693 -export type RunningViewTransition = null;
694 -
695 -export function startGestureTransition(
696 - suspendedState: null | SuspendedState,
697 - rootContainer: Container,
698 - timeline: GestureTimeline,
699 - rangeStart: number,
700 - rangeEnd: number,
701 - transitionTypes: null | TransitionTypes,
702 - mutationCallback: () => void,
703 - animateCallback: () => void,
704 - errorCallback: mixed => void,
705 - finishedAnimation: () => void, // Profiling-only
706 -): null | RunningViewTransition {
707 - mutationCallback();
708 - animateCallback();
709 - if (enableProfilerTimer) {
710 - finishedAnimation();
711 - }
712 - return null;
713 -}
714 -
715 -export function stopViewTransition(transition: RunningViewTransition) {}
716 -
717 -export function addViewTransitionFinishedListener(
718 - transition: RunningViewTransition,
719 - callback: () => void,
720 -) {
721 - callback();
722 -}
723 -
724 -export type ViewTransitionInstance = null | {name: string, ...};
725 -
726 -export function createViewTransitionInstance(
727 - name: string,
728 -): ViewTransitionInstance {
729 - return null;
730 -}
731 -
732 -export type GestureTimeline = null;
733 -
734 -export function getCurrentGestureOffset(provider: GestureTimeline): number {
735 - throw new Error(
736 - 'startGestureTransition is not yet supported in React Native.',
737 - );
738 -}
739 -
740 -export function clearContainer(container: Container): void {
741 - // TODO Implement this for React Native
742 - // UIManager does not expose a "remove all" type method.
743 -}
744 -
745 -export function unhideTextInstance(
746 - textInstance: TextInstance,
747 - text: string,
748 -): void {
749 - throw new Error('Not yet implemented.');
750 -}
751 -
752 -export {getClosestInstanceFromNode as getInstanceFromNode};
753 -
754 -export function beforeActiveInstanceBlur(internalInstanceHandle: Object) {
755 - // noop
756 -}
757 -
758 -export function afterActiveInstanceBlur() {
759 - // noop
760 -}
761 -
762 -export function preparePortalMount(portalInstance: Instance): void {
763 - // noop
764 -}
765 -
766 -export function detachDeletedInstance(node: Instance): void {
767 - // noop
768 -}
769 -
770 -export function requestPostPaintCallback(callback: (time: number) => void) {
771 - // noop
772 -}
773 -
774 -export function maySuspendCommit(type: Type, props: Props): boolean {
775 - return false;
776 -}
777 -
778 -export function maySuspendCommitOnUpdate(
779 - type: Type,
780 - oldProps: Props,
781 - newProps: Props,
782 -): boolean {
783 - return false;
784 -}
785 -
786 -export function maySuspendCommitInSyncRender(
787 - type: Type,
788 - props: Props,
789 -): boolean {
790 - return false;
791 -}
792 -
793 -export function preloadInstance(
794 - instance: Instance,
795 - type: Type,
796 - props: Props,
797 -): boolean {
798 - // Return false to indicate it's already loaded
799 - return true;
800 -}
801 -
802 -export opaque type SuspendedState = null;
803 -
804 -export function startSuspendingCommit(): SuspendedState {
805 - return null;
806 -}
807 -
808 -export function suspendInstance(
809 - state: SuspendedState,
810 - instance: Instance,
811 - type: Type,
812 - props: Props,
813 -): void {}
814 -
815 -export function suspendOnActiveViewTransition(
816 - state: SuspendedState,
817 - container: Container,
818 -): void {}
819 -
820 -export function waitForCommitToBeReady(
821 - state: SuspendedState,
822 - timeoutOffset: number,
823 -): null {
824 - return null;
825 -}
826 -
827 -export function getSuspendedCommitReason(
828 - state: SuspendedState,
829 - rootContainer: Container,
830 -): null | string {
831 - return null;
832 -}
833 -
834 -export const NotPendingTransition: TransitionStatus = null;
835 -export const HostTransitionContext: ReactContext<TransitionStatus> = {
836 - $$typeof: REACT_CONTEXT_TYPE,
837 - Provider: (null: any),
838 - Consumer: (null: any),
839 - _currentValue: NotPendingTransition,
840 - _currentValue2: NotPendingTransition,
841 - _threadCount: 0,
842 -};
843 -
844 -export type FormInstance = Instance;
845 -export function resetFormInstance(form: Instance): void {}
packages/react-native-renderer/src/ReactNativeAttributePayload.js deleted
-492
@@ -1,492 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -// Modules provided by RN:
11 -import {
12 - deepDiffer,
13 - flattenStyle,
14 -} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
15 -import isArray from 'shared/isArray';
16 -
17 -import type {AttributeConfiguration} from './ReactNativeTypes';
18 -
19 -const emptyObject = {};
20 -
21 -/**
22 - * Create a payload that contains all the updates between two sets of props.
23 - *
24 - * These helpers are all encapsulated into a single module, because they use
25 - * mutation as a performance optimization which leads to subtle shared
26 - * dependencies between the code paths. To avoid this mutable state leaking
27 - * across modules, I've kept them isolated to this module.
28 - */
29 -
30 -type NestedNode = Array<NestedNode> | Object;
31 -
32 -// Tracks removed keys
33 -let removedKeys: {[string]: boolean} | null = null;
34 -let removedKeyCount = 0;
35 -
36 -const deepDifferOptions = {
37 - unsafelyIgnoreFunctions: true,
38 -};
39 -
40 -function defaultDiffer(prevProp: mixed, nextProp: mixed): boolean {
41 - if (typeof nextProp !== 'object' || nextProp === null) {
42 - // Scalars have already been checked for equality
43 - return true;
44 - } else {
45 - // For objects and arrays, the default diffing algorithm is a deep compare
46 - return deepDiffer(prevProp, nextProp, deepDifferOptions);
47 - }
48 -}
49 -
50 -function restoreDeletedValuesInNestedArray(
51 - updatePayload: Object,
52 - node: NestedNode,
53 - validAttributes: AttributeConfiguration,
54 -) {
55 - if (isArray(node)) {
56 - let i = node.length;
57 - while (i-- && removedKeyCount > 0) {
58 - restoreDeletedValuesInNestedArray(
59 - updatePayload,
60 - node[i],
61 - validAttributes,
62 - );
63 - }
64 - } else if (node && removedKeyCount > 0) {
65 - const obj = node;
66 - for (const propKey in removedKeys) {
67 - // $FlowFixMe[incompatible-use] found when upgrading Flow
68 - if (!removedKeys[propKey]) {
69 - continue;
70 - }
71 - let nextProp = obj[propKey];
72 - if (nextProp === undefined) {
73 - continue;
74 - }
75 -
76 - const attributeConfig = validAttributes[propKey];
77 - if (!attributeConfig) {
78 - continue; // not a valid native prop
79 - }
80 -
81 - if (typeof nextProp === 'function') {
82 - // $FlowFixMe[incompatible-type] found when upgrading Flow
83 - nextProp = true;
84 - }
85 - if (typeof nextProp === 'undefined') {
86 - // $FlowFixMe[incompatible-type] found when upgrading Flow
87 - nextProp = null;
88 - }
89 -
90 - if (typeof attributeConfig !== 'object') {
91 - // case: !Object is the default case
92 - updatePayload[propKey] = nextProp;
93 - } else if (
94 - typeof attributeConfig.diff === 'function' ||
95 - typeof attributeConfig.process === 'function'
96 - ) {
97 - // case: CustomAttributeConfiguration
98 - const nextValue =
99 - typeof attributeConfig.process === 'function'
100 - ? attributeConfig.process(nextProp)
101 - : nextProp;
102 - updatePayload[propKey] = nextValue;
103 - }
104 - // $FlowFixMe[incompatible-use] found when upgrading Flow
105 - removedKeys[propKey] = false;
106 - removedKeyCount--;
107 - }
108 - }
109 -}
110 -
111 -function diffNestedArrayProperty(
112 - updatePayload: null | Object,
113 - prevArray: Array<NestedNode>,
114 - nextArray: Array<NestedNode>,
115 - validAttributes: AttributeConfiguration,
116 -): null | Object {
117 - const minLength =
118 - prevArray.length < nextArray.length ? prevArray.length : nextArray.length;
119 - let i;
120 - for (i = 0; i < minLength; i++) {
121 - // Diff any items in the array in the forward direction. Repeated keys
122 - // will be overwritten by later values.
123 - updatePayload = diffNestedProperty(
124 - updatePayload,
125 - prevArray[i],
126 - nextArray[i],
127 - validAttributes,
128 - );
129 - }
130 - for (; i < prevArray.length; i++) {
131 - // Clear out all remaining properties.
132 - updatePayload = clearNestedProperty(
133 - updatePayload,
134 - prevArray[i],
135 - validAttributes,
136 - );
137 - }
138 - for (; i < nextArray.length; i++) {
139 - // Add all remaining properties.
140 - updatePayload = addNestedProperty(
141 - updatePayload,
142 - nextArray[i],
143 - validAttributes,
144 - );
145 - }
146 - return updatePayload;
147 -}
148 -
149 -function diffNestedProperty(
150 - updatePayload: null | Object,
151 - prevProp: NestedNode,
152 - nextProp: NestedNode,
153 - validAttributes: AttributeConfiguration,
154 -): null | Object {
155 - if (!updatePayload && prevProp === nextProp) {
156 - // If no properties have been added, then we can bail out quickly on object
157 - // equality.
158 - return updatePayload;
159 - }
160 -
161 - if (!prevProp || !nextProp) {
162 - if (nextProp) {
163 - return addNestedProperty(updatePayload, nextProp, validAttributes);
164 - }
165 - if (prevProp) {
166 - return clearNestedProperty(updatePayload, prevProp, validAttributes);
167 - }
168 - return updatePayload;
169 - }
170 -
171 - if (!isArray(prevProp) && !isArray(nextProp)) {
172 - // Both are leaves, we can diff the leaves.
173 - return diffProperties(updatePayload, prevProp, nextProp, validAttributes);
174 - }
175 -
176 - if (isArray(prevProp) && isArray(nextProp)) {
177 - // Both are arrays, we can diff the arrays.
178 - return diffNestedArrayProperty(
179 - updatePayload,
180 - prevProp,
181 - nextProp,
182 - validAttributes,
183 - );
184 - }
185 -
186 - if (isArray(prevProp)) {
187 - return diffProperties(
188 - updatePayload,
189 - flattenStyle(prevProp),
190 - nextProp,
191 - validAttributes,
192 - );
193 - }
194 -
195 - return diffProperties(
196 - updatePayload,
197 - prevProp,
198 - flattenStyle(nextProp),
199 - validAttributes,
200 - );
201 -}
202 -
203 -/**
204 - * addNestedProperty takes a single set of props and valid attribute
205 - * attribute configurations. It processes each prop and adds it to the
206 - * updatePayload.
207 - */
208 -function addNestedProperty(
209 - updatePayload: null | Object,
210 - nextProp: NestedNode,
211 - validAttributes: AttributeConfiguration,
212 -): $FlowFixMe {
213 - if (!nextProp) {
214 - return updatePayload;
215 - }
216 -
217 - if (!isArray(nextProp)) {
218 - // Add each property of the leaf.
219 - return addProperties(updatePayload, nextProp, validAttributes);
220 - }
221 -
222 - for (let i = 0; i < nextProp.length; i++) {
223 - // Add all the properties of the array.
224 - updatePayload = addNestedProperty(
225 - updatePayload,
226 - nextProp[i],
227 - validAttributes,
228 - );
229 - }
230 -
231 - return updatePayload;
232 -}
233 -
234 -/**
235 - * clearNestedProperty takes a single set of props and valid attributes. It
236 - * adds a null sentinel to the updatePayload, for each prop key.
237 - */
238 -function clearNestedProperty(
239 - updatePayload: null | Object,
240 - prevProp: NestedNode,
241 - validAttributes: AttributeConfiguration,
242 -): null | Object {
243 - if (!prevProp) {
244 - return updatePayload;
245 - }
246 -
247 - if (!isArray(prevProp)) {
248 - // Add each property of the leaf.
249 - return clearProperties(updatePayload, prevProp, validAttributes);
250 - }
251 -
252 - for (let i = 0; i < prevProp.length; i++) {
253 - // Add all the properties of the array.
254 - updatePayload = clearNestedProperty(
255 - updatePayload,
256 - prevProp[i],
257 - validAttributes,
258 - );
259 - }
260 - return updatePayload;
261 -}
262 -
263 -/**
264 - * diffProperties takes two sets of props and a set of valid attributes
265 - * and write to updatePayload the values that changed or were deleted.
266 - * If no updatePayload is provided, a new one is created and returned if
267 - * anything changed.
268 - */
269 -function diffProperties(
270 - updatePayload: null | Object,
271 - prevProps: Object,
272 - nextProps: Object,
273 - validAttributes: AttributeConfiguration,
274 -): null | Object {
275 - let attributeConfig;
276 - let nextProp;
277 - let prevProp;
278 -
279 - for (const propKey in nextProps) {
280 - attributeConfig = validAttributes[propKey];
281 - if (!attributeConfig) {
282 - continue; // not a valid native prop
283 - }
284 -
285 - prevProp = prevProps[propKey];
286 - nextProp = nextProps[propKey];
287 -
288 - // functions are converted to booleans as markers that the associated
289 - // events should be sent from native.
290 - if (typeof nextProp === 'function') {
291 - nextProp = (true: any);
292 - // If nextProp is not a function, then don't bother changing prevProp
293 - // since nextProp will win and go into the updatePayload regardless.
294 - if (typeof prevProp === 'function') {
295 - prevProp = (true: any);
296 - }
297 - }
298 -
299 - // An explicit value of undefined is treated as a null because it overrides
300 - // any other preceding value.
301 - if (typeof nextProp === 'undefined') {
302 - nextProp = (null: any);
303 - if (typeof prevProp === 'undefined') {
304 - prevProp = (null: any);
305 - }
306 - }
307 -
308 - if (removedKeys) {
309 - removedKeys[propKey] = false;
310 - }
311 -
312 - if (updatePayload && updatePayload[propKey] !== undefined) {
313 - // Something else already triggered an update to this key because another
314 - // value diffed. Since we're now later in the nested arrays our value is
315 - // more important so we need to calculate it and override the existing
316 - // value. It doesn't matter if nothing changed, we'll set it anyway.
317 -
318 - // Pattern match on: attributeConfig
319 - if (typeof attributeConfig !== 'object') {
320 - // case: !Object is the default case
321 - updatePayload[propKey] = nextProp;
322 - } else if (
323 - typeof attributeConfig.diff === 'function' ||
324 - typeof attributeConfig.process === 'function'
325 - ) {
326 - // case: CustomAttributeConfiguration
327 - const nextValue =
328 - typeof attributeConfig.process === 'function'
329 - ? attributeConfig.process(nextProp)
330 - : nextProp;
331 - updatePayload[propKey] = nextValue;
332 - }
333 - continue;
334 - }
335 -
336 - if (prevProp === nextProp) {
337 - continue; // nothing changed
338 - }
339 -
340 - // Pattern match on: attributeConfig
341 - if (typeof attributeConfig !== 'object') {
342 - // case: !Object is the default case
343 - if (defaultDiffer(prevProp, nextProp)) {
344 - // a normal leaf has changed
345 - (updatePayload || (updatePayload = ({}: {[string]: $FlowFixMe})))[
346 - propKey
347 - ] = nextProp;
348 - }
349 - } else if (
350 - typeof attributeConfig.diff === 'function' ||
351 - typeof attributeConfig.process === 'function'
352 - ) {
353 - // case: CustomAttributeConfiguration
354 - const shouldUpdate =
355 - prevProp === undefined ||
356 - (typeof attributeConfig.diff === 'function'
357 - ? attributeConfig.diff(prevProp, nextProp)
358 - : defaultDiffer(prevProp, nextProp));
359 - if (shouldUpdate) {
360 - const nextValue =
361 - typeof attributeConfig.process === 'function'
362 - ? // $FlowFixMe[incompatible-use] found when upgrading Flow
363 - attributeConfig.process(nextProp)
364 - : nextProp;
365 - (updatePayload || (updatePayload = ({}: {[string]: $FlowFixMe})))[
366 - propKey
367 - ] = nextValue;
368 - }
369 - } else {
370 - // default: fallthrough case when nested properties are defined
371 - removedKeys = null;
372 - removedKeyCount = 0;
373 - // We think that attributeConfig is not CustomAttributeConfiguration at
374 - // this point so we assume it must be AttributeConfiguration.
375 - updatePayload = diffNestedProperty(
376 - updatePayload,
377 - prevProp,
378 - nextProp,
379 - ((attributeConfig: any): AttributeConfiguration),
380 - );
381 - if (removedKeyCount > 0 && updatePayload) {
382 - restoreDeletedValuesInNestedArray(
383 - updatePayload,
384 - nextProp,
385 - ((attributeConfig: any): AttributeConfiguration),
386 - );
387 - removedKeys = null;
388 - }
389 - }
390 - }
391 -
392 - // Also iterate through all the previous props to catch any that have been
393 - // removed and make sure native gets the signal so it can reset them to the
394 - // default.
395 - for (const propKey in prevProps) {
396 - if (nextProps[propKey] !== undefined) {
397 - continue; // we've already covered this key in the previous pass
398 - }
399 - attributeConfig = validAttributes[propKey];
400 - if (!attributeConfig) {
401 - continue; // not a valid native prop
402 - }
403 -
404 - if (updatePayload && updatePayload[propKey] !== undefined) {
405 - // This was already updated to a diff result earlier.
406 - continue;
407 - }
408 -
409 - prevProp = prevProps[propKey];
410 - if (prevProp === undefined) {
411 - continue; // was already empty anyway
412 - }
413 - // Pattern match on: attributeConfig
414 - if (
415 - typeof attributeConfig !== 'object' ||
416 - typeof attributeConfig.diff === 'function' ||
417 - typeof attributeConfig.process === 'function'
418 - ) {
419 - // case: CustomAttributeConfiguration | !Object
420 - // Flag the leaf property for removal by sending a sentinel.
421 - (updatePayload || (updatePayload = ({}: {[string]: $FlowFixMe})))[
422 - propKey
423 - ] = null;
424 - if (!removedKeys) {
425 - removedKeys = ({}: {[string]: boolean});
426 - }
427 - if (!removedKeys[propKey]) {
428 - removedKeys[propKey] = true;
429 - removedKeyCount++;
430 - }
431 - } else {
432 - // default:
433 - // This is a nested attribute configuration where all the properties
434 - // were removed so we need to go through and clear out all of them.
435 - updatePayload = clearNestedProperty(
436 - updatePayload,
437 - prevProp,
438 - ((attributeConfig: any): AttributeConfiguration),
439 - );
440 - }
441 - }
442 - return updatePayload;
443 -}
444 -
445 -/**
446 - * addProperties adds all the valid props to the payload after being processed.
447 - */
448 -function addProperties(
449 - updatePayload: null | Object,
450 - props: Object,
451 - validAttributes: AttributeConfiguration,
452 -): null | Object {
453 - // TODO: Fast path
454 - return diffProperties(updatePayload, emptyObject, props, validAttributes);
455 -}
456 -
457 -/**
458 - * clearProperties clears all the previous props by adding a null sentinel
459 - * to the payload for each valid key.
460 - */
461 -function clearProperties(
462 - updatePayload: null | Object,
463 - prevProps: Object,
464 - validAttributes: AttributeConfiguration,
465 -): null | Object {
466 - // TODO: Fast path
467 - return diffProperties(updatePayload, prevProps, emptyObject, validAttributes);
468 -}
469 -
470 -export function create(
471 - props: Object,
472 - validAttributes: AttributeConfiguration,
473 -): null | Object {
474 - return addProperties(
475 - null, // updatePayload
476 - props,
477 - validAttributes,
478 - );
479 -}
480 -
481 -export function diff(
482 - prevProps: Object,
483 - nextProps: Object,
484 - validAttributes: AttributeConfiguration,
485 -): null | Object {
486 - return diffProperties(
487 - null, // updatePayload
488 - prevProps,
489 - nextProps,
490 - validAttributes,
491 - );
492 -}
packages/react-native-renderer/src/ReactNativeComponentTree.js deleted
-52
@@ -1,52 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - */
7 -
8 -const instanceCache = new Map();
9 -const instanceProps = new Map();
10 -
11 -export function precacheFiberNode(hostInst, tag) {
12 - instanceCache.set(tag, hostInst);
13 -}
14 -
15 -export function uncacheFiberNode(tag) {
16 - instanceCache.delete(tag);
17 - instanceProps.delete(tag);
18 -}
19 -
20 -function getInstanceFromTag(tag) {
21 - return instanceCache.get(tag) || null;
22 -}
23 -
24 -function getTagFromInstance(inst) {
25 - let nativeInstance = inst.stateNode;
26 - let tag = nativeInstance._nativeTag;
27 - if (tag === undefined && nativeInstance.canonical != null) {
28 - // For compatibility with Fabric
29 - tag = nativeInstance.canonical.nativeTag;
30 - nativeInstance = nativeInstance.canonical.publicInstance;
31 - }
32 -
33 - if (!tag) {
34 - throw new Error('All native instances should have a tag.');
35 - }
36 -
37 - return nativeInstance;
38 -}
39 -
40 -export {
41 - getInstanceFromTag as getClosestInstanceFromNode,
42 - getInstanceFromTag as getInstanceFromNode,
43 - getTagFromInstance as getNodeFromInstance,
44 -};
45 -
46 -export function getFiberCurrentPropsFromNode(stateNode) {
47 - return instanceProps.get(stateNode._nativeTag) || null;
48 -}
49 -
50 -export function updateFiberProps(tag, props) {
51 - instanceProps.set(tag, props);
52 -}
packages/react-native-renderer/src/ReactNativeEventEmitter.js deleted
-243
@@ -1,243 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -import type {
11 - AnyNativeEvent,
12 - LegacyPluginModule,
13 -} from './legacy-events/PluginModuleType';
14 -import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
15 -import type {ReactSyntheticEvent} from './legacy-events/ReactSyntheticEventType';
16 -import type {TopLevelType} from './legacy-events/TopLevelEventTypes';
17 -
18 -import {
19 - registrationNameModules,
20 - plugins,
21 -} from './legacy-events/EventPluginRegistry';
22 -import {batchedUpdates} from './legacy-events/ReactGenericBatching';
23 -import {runEventsInBatch} from './legacy-events/EventBatching';
24 -import getListener from './ReactNativeGetListener';
25 -import accumulateInto from './legacy-events/accumulateInto';
26 -
27 -import {getInstanceFromNode} from './ReactNativeComponentTree';
28 -
29 -export {getListener, registrationNameModules as registrationNames};
30 -
31 -/**
32 - * Version of `ReactBrowserEventEmitter` that works on the receiving side of a
33 - * serialized worker boundary.
34 - */
35 -
36 -// Shared default empty native event - conserve memory.
37 -const EMPTY_NATIVE_EVENT = (({}: any): AnyNativeEvent);
38 -
39 -/**
40 - * Selects a subsequence of `Touch`es, without destroying `touches`.
41 - *
42 - * @param {Array<Touch>} touches Deserialized touch objects.
43 - * @param {Array<number>} indices Indices by which to pull subsequence.
44 - * @return {Array<Touch>} Subsequence of touch objects.
45 - */
46 -// $FlowFixMe[missing-local-annot]
47 -function touchSubsequence(touches, indices) {
48 - const ret = [];
49 - for (let i = 0; i < indices.length; i++) {
50 - ret.push(touches[indices[i]]);
51 - }
52 - return ret;
53 -}
54 -
55 -/**
56 - * TODO: Pool all of this.
57 - *
58 - * Destroys `touches` by removing touch objects at indices `indices`. This is
59 - * to maintain compatibility with W3C touch "end" events, where the active
60 - * touches don't include the set that has just been "ended".
61 - *
62 - * @param {Array<Touch>} touches Deserialized touch objects.
63 - * @param {Array<number>} indices Indices to remove from `touches`.
64 - * @return {Array<Touch>} Subsequence of removed touch objects.
65 - */
66 -function removeTouchesAtIndices(
67 - touches: Array<Object>,
68 - indices: Array<number>,
69 -): Array<Object> {
70 - const rippedOut = [];
71 - // use an unsafe downcast to alias to nullable elements,
72 - // so we can delete and then compact.
73 - const temp: Array<?Object> = (touches: Array<any>);
74 - for (let i = 0; i < indices.length; i++) {
75 - const index = indices[i];
76 - rippedOut.push(touches[index]);
77 - temp[index] = null;
78 - }
79 - let fillAt = 0;
80 - for (let j = 0; j < temp.length; j++) {
81 - const cur = temp[j];
82 - if (cur !== null) {
83 - temp[fillAt++] = cur;
84 - }
85 - }
86 - temp.length = fillAt;
87 - return rippedOut;
88 -}
89 -
90 -/**
91 - * Internal version of `receiveEvent` in terms of normalized (non-tag)
92 - * `rootNodeID`.
93 - *
94 - * @see receiveEvent.
95 - *
96 - * @param {rootNodeID} rootNodeID React root node ID that event occurred on.
97 - * @param {TopLevelType} topLevelType Top level type of event.
98 - * @param {?object} nativeEventParam Object passed from native.
99 - */
100 -function _receiveRootNodeIDEvent(
101 - rootNodeID: number,
102 - topLevelType: TopLevelType,
103 - nativeEventParam: ?AnyNativeEvent,
104 -) {
105 - const nativeEvent = nativeEventParam || EMPTY_NATIVE_EVENT;
106 - const inst = getInstanceFromNode(rootNodeID);
107 -
108 - let target = null;
109 - if (inst != null) {
110 - target = inst.stateNode;
111 - }
112 -
113 - batchedUpdates(function () {
114 - runExtractedPluginEventsInBatch(topLevelType, inst, nativeEvent, target);
115 - });
116 - // React Native doesn't use ReactControlledComponent but if it did, here's
117 - // where it would do it.
118 -}
119 -
120 -/**
121 - * Allows registered plugins an opportunity to extract events from top-level
122 - * native browser events.
123 - *
124 - * @return {*} An accumulation of synthetic events.
125 - * @internal
126 - */
127 -function extractPluginEvents(
128 - topLevelType: TopLevelType,
129 - targetInst: null | Fiber,
130 - nativeEvent: AnyNativeEvent,
131 - nativeEventTarget: null | EventTarget,
132 -): Array<ReactSyntheticEvent> | ReactSyntheticEvent | null {
133 - let events: Array<ReactSyntheticEvent> | ReactSyntheticEvent | null = null;
134 - const legacyPlugins = ((plugins: any): Array<
135 - LegacyPluginModule<AnyNativeEvent>,
136 - >);
137 - for (let i = 0; i < legacyPlugins.length; i++) {
138 - // Not every plugin in the ordering may be loaded at runtime.
139 - const possiblePlugin = legacyPlugins[i];
140 - if (possiblePlugin) {
141 - const extractedEvents = possiblePlugin.extractEvents(
142 - topLevelType,
143 - targetInst,
144 - nativeEvent,
145 - nativeEventTarget,
146 - );
147 - if (extractedEvents) {
148 - events = accumulateInto(events, extractedEvents);
149 - }
150 - }
151 - }
152 - return events;
153 -}
154 -
155 -function runExtractedPluginEventsInBatch(
156 - topLevelType: TopLevelType,
157 - targetInst: null | Fiber,
158 - nativeEvent: AnyNativeEvent,
159 - nativeEventTarget: null | EventTarget,
160 -) {
161 - const events = extractPluginEvents(
162 - topLevelType,
163 - targetInst,
164 - nativeEvent,
165 - nativeEventTarget,
166 - );
167 - runEventsInBatch(events);
168 -}
169 -
170 -/**
171 - * Publicly exposed method on module for native objc to invoke when a top
172 - * level event is extracted.
173 - * @param {rootNodeID} rootNodeID React root node ID that event occurred on.
174 - * @param {TopLevelType} topLevelType Top level type of event.
175 - * @param {object} nativeEventParam Object passed from native.
176 - */
177 -export function receiveEvent(
178 - rootNodeID: number,
179 - topLevelType: TopLevelType,
180 - nativeEventParam: AnyNativeEvent,
181 -) {
182 - _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam);
183 -}
184 -
185 -/**
186 - * Simple multi-wrapper around `receiveEvent` that is intended to receive an
187 - * efficient representation of `Touch` objects, and other information that
188 - * can be used to construct W3C compliant `Event` and `Touch` lists.
189 - *
190 - * This may create dispatch behavior that differs than web touch handling. We
191 - * loop through each of the changed touches and receive it as a single event.
192 - * So two `touchStart`/`touchMove`s that occur simultaneously are received as
193 - * two separate touch event dispatches - when they arguably should be one.
194 - *
195 - * This implementation reuses the `Touch` objects themselves as the `Event`s
196 - * since we dispatch an event for each touch (though that might not be spec
197 - * compliant). The main purpose of reusing them is to save allocations.
198 - *
199 - * TODO: Dispatch multiple changed touches in one event. The bubble path
200 - * could be the first common ancestor of all the `changedTouches`.
201 - *
202 - * One difference between this behavior and W3C spec: cancelled touches will
203 - * not appear in `.touches`, or in any future `.touches`, though they may
204 - * still be "actively touching the surface".
205 - *
206 - * Web desktop polyfills only need to construct a fake touch event with
207 - * identifier 0, also abandoning traditional click handlers.
208 - */
209 -export function receiveTouches(
210 - eventTopLevelType: TopLevelType,
211 - touches: Array<Object>,
212 - changedIndices: Array<number>,
213 -) {
214 - const changedTouches =
215 - eventTopLevelType === 'topTouchEnd' ||
216 - eventTopLevelType === 'topTouchCancel'
217 - ? removeTouchesAtIndices(touches, changedIndices)
218 - : touchSubsequence(touches, changedIndices);
219 -
220 - for (let jj = 0; jj < changedTouches.length; jj++) {
221 - const touch = changedTouches[jj];
222 - // Touch objects can fulfill the role of `DOM` `Event` objects if we set
223 - // the `changedTouches`/`touches`. This saves allocations.
224 - touch.changedTouches = changedTouches;
225 - touch.touches = touches;
226 - const nativeEvent = touch;
227 - let rootNodeID = null;
228 - const target = nativeEvent.target;
229 - if (target !== null && target !== undefined) {
230 - if (target < 1) {
231 - if (__DEV__) {
232 - console.error(
233 - 'A view is reporting that a touch occurred on tag zero.',
234 - );
235 - }
236 - } else {
237 - rootNodeID = target;
238 - }
239 - }
240 - // $FlowFixMe[incompatible-call] Shouldn't we *not* call it if rootNodeID is null?
241 - _receiveRootNodeIDEvent(rootNodeID, eventTopLevelType, nativeEvent);
242 - }
243 -}
packages/react-native-renderer/src/ReactNativeFiberHostComponent.js deleted
-128
@@ -1,128 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -import type {ViewConfig} from './ReactNativeTypes';
11 -import type {
12 - LegacyPublicInstance,
13 - MeasureOnSuccessCallback,
14 - MeasureInWindowOnSuccessCallback,
15 - MeasureLayoutOnSuccessCallback,
16 -} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
17 -import type {Instance} from './ReactFiberConfigNative';
18 -
19 -// Modules provided by RN:
20 -import {
21 - TextInputState,
22 - UIManager,
23 -} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
24 -
25 -import {create} from './ReactNativeAttributePayload';
26 -import {
27 - mountSafeCallback_NOT_REALLY_SAFE,
28 - warnForStyleProps,
29 -} from './NativeMethodsMixinUtils';
30 -
31 -class ReactNativeFiberHostComponent implements LegacyPublicInstance {
32 - _children: Array<Instance | number>;
33 - _nativeTag: number;
34 - _internalFiberInstanceHandleDEV: Object;
35 - viewConfig: ViewConfig;
36 -
37 - constructor(
38 - tag: number,
39 - viewConfig: ViewConfig,
40 - internalInstanceHandleDEV: Object,
41 - ) {
42 - this._nativeTag = tag;
43 - this._children = [];
44 - this.viewConfig = viewConfig;
45 - if (__DEV__) {
46 - this._internalFiberInstanceHandleDEV = internalInstanceHandleDEV;
47 - }
48 - }
49 -
50 - blur() {
51 - TextInputState.blurTextInput(this);
52 - }
53 -
54 - focus() {
55 - TextInputState.focusTextInput(this);
56 - }
57 -
58 - measure(callback: MeasureOnSuccessCallback) {
59 - UIManager.measure(
60 - this._nativeTag,
61 - mountSafeCallback_NOT_REALLY_SAFE(this, callback),
62 - );
63 - }
64 -
65 - measureInWindow(callback: MeasureInWindowOnSuccessCallback) {
66 - UIManager.measureInWindow(
67 - this._nativeTag,
68 - mountSafeCallback_NOT_REALLY_SAFE(this, callback),
69 - );
70 - }
71 -
72 - measureLayout(
73 - relativeToNativeNode: number | LegacyPublicInstance,
74 - onSuccess: MeasureLayoutOnSuccessCallback,
75 - onFail?: () => void /* currently unused */,
76 - ) {
77 - let relativeNode: ?number;
78 -
79 - if (typeof relativeToNativeNode === 'number') {
80 - // Already a node handle
81 - relativeNode = relativeToNativeNode;
82 - } else {
83 - const nativeNode: ReactNativeFiberHostComponent =
84 - (relativeToNativeNode: any);
85 - if (nativeNode._nativeTag) {
86 - relativeNode = nativeNode._nativeTag;
87 - }
88 - }
89 -
90 - if (relativeNode == null) {
91 - if (__DEV__) {
92 - console.error(
93 - 'ref.measureLayout must be called with a node handle or a ref to a native component.',
94 - );
95 - }
96 -
97 - return;
98 - }
99 -
100 - UIManager.measureLayout(
101 - this._nativeTag,
102 - relativeNode,
103 - mountSafeCallback_NOT_REALLY_SAFE(this, onFail),
104 - mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess),
105 - );
106 - }
107 -
108 - setNativeProps(nativeProps: Object) {
109 - if (__DEV__) {
110 - warnForStyleProps(nativeProps, this.viewConfig.validAttributes);
111 - }
112 -
113 - const updatePayload = create(nativeProps, this.viewConfig.validAttributes);
114 -
115 - // Avoid the overhead of bridge calls if there's no update.
116 - // This is an expensive no-op for Android, and causes an unnecessary
117 - // view invalidation for certain components (eg RCTTextInput) on iOS.
118 - if (updatePayload != null) {
119 - UIManager.updateView(
120 - this._nativeTag,
121 - this.viewConfig.uiViewClassName,
122 - updatePayload,
123 - );
124 - }
125 - }
126 -}
127 -
128 -export default ReactNativeFiberHostComponent;
packages/react-native-renderer/src/ReactNativeFiberInspector.js
+3 -63
@@ -17,15 +17,8 @@ import {
17 import getComponentNameFromType from 'shared/getComponentNameFromType';
18 import {HostComponent} from 'react-reconciler/src/ReactWorkTags';
19 // Module provided by RN:
20 -import {
21 - UIManager,
22 - getNodeFromPublicInstance,
23 -} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
24 -import {getClosestInstanceFromNode} from './ReactNativeComponentTree';
25 -import {
26 - getNodeFromInternalInstanceHandle,
27 - findNodeHandle,
28 -} from './ReactNativePublicCompat';
20 +import {getNodeFromPublicInstance} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
21 +import {getNodeFromInternalInstanceHandle} from './ReactNativePublicCompat';
22 import {getStackByFiberInDevAndProd} from 'react-reconciler/src/ReactFiberComponentStack';
23
24 let getInspectorDataForInstance: (
@@ -43,7 +36,6 @@ if (__DEV__) {
36 return {
37 props: getHostProps(fiber),
38 measure: callback => {
46 - // If this is Fabric, we'll find a shadow node and use that to measure.
39 const hostFiber = findCurrentHostFiber(fiber);
40 const node =
41 hostFiber != null &&
@@ -52,8 +44,6 @@ if (__DEV__) {
44
45 if (node) {
46 nativeFabricUIManager.measure(node, callback);
55 - } else {
56 - return UIManager.measure(getHostNode(fiber), callback);
47 }
48 },
49 };
@@ -61,22 +51,6 @@ if (__DEV__) {
51 }));
52 };
53
64 - const getHostNode = function (fiber: Fiber | null) {
65 - let hostNode;
66 - // look for children first for the hostNode
67 - // as composite fibers do not have a hostNode
68 - while (fiber) {
69 - if (fiber.stateNode !== null && fiber.tag === HostComponent) {
70 - hostNode = findNodeHandle(fiber.stateNode);
71 - }
72 - if (hostNode) {
73 - return hostNode;
74 - }
75 - fiber = fiber.child;
76 - }
77 - return null;
78 - };
79 -
54 const getHostProps = function (fiber: Fiber) {
55 const host = findCurrentHostFiber(fiber);
56 if (host) {
@@ -156,17 +130,6 @@ if (__DEV__) {
130 };
131 }
132
159 -function getInspectorDataForViewTag(viewTag: number): InspectorData {
160 - if (__DEV__) {
161 - const closestInstance = getClosestInstanceFromNode(viewTag);
162 - return getInspectorDataForInstance(closestInstance);
163 - } else {
164 - throw new Error(
165 - 'getInspectorDataForViewTag() is not available in production',
166 - );
167 - }
168 -}
169 -
133 function getInspectorDataForViewAtPoint(
134 inspectedView: Object,
135 locationX: number,
@@ -222,25 +185,6 @@ function getInspectorDataForViewAtPoint(
185 );
186 },
187 );
225 - } else if (inspectedView._internalFiberInstanceHandleDEV != null) {
226 - // For Paper we fall back to the old strategy using the React tag.
227 - UIManager.findSubviewIn(
228 - findNodeHandle(inspectedView),
229 - [locationX, locationY],
230 - (nativeViewTag, left, top, width, height) => {
231 - const inspectorData = getInspectorDataForInstance(
232 - getClosestInstanceFromNode(nativeViewTag),
233 - );
234 - callback({
235 - ...inspectorData,
236 - pointerY: locationY,
237 - frame: {left, top, width, height},
238 - touchedViewTag: nativeViewTag,
239 - // $FlowExpectedError[incompatible-call]
240 - closestPublicInstance: nativeViewTag,
241 - });
242 - },
243 - );
188 } else {
189 console.error(
190 'getInspectorDataForViewAtPoint expects to receive a host component',
@@ -255,8 +199,4 @@ function getInspectorDataForViewAtPoint(
199 }
200 }
201
258 -export {
259 - getInspectorDataForInstance,
260 - getInspectorDataForViewAtPoint,
261 - getInspectorDataForViewTag,
262 -};
202 +export {getInspectorDataForInstance, getInspectorDataForViewAtPoint};
packages/react-native-renderer/src/ReactNativeGlobalResponderHandler.js deleted
-24
@@ -1,24 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -// Module provided by RN:
11 -import {UIManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
12 -
13 -const ReactNativeGlobalResponderHandler = {
14 - onChange: function (from: any, to: any, blockNativeResponder: boolean) {
15 - if (to !== null) {
16 - const tag = to.stateNode._nativeTag;
17 - UIManager.setJSResponder(tag, blockNativeResponder);
18 - } else {
19 - UIManager.clearJSResponder();
20 - }
21 - },
22 -};
23 -
24 -export default ReactNativeGlobalResponderHandler;
packages/react-native-renderer/src/ReactNativeInjection.js deleted
-41
@@ -1,41 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -import './ReactNativeInjectionShared';
11 -
12 -import {
13 - getFiberCurrentPropsFromNode,
14 - getInstanceFromNode,
15 - getNodeFromInstance,
16 -} from './ReactNativeComponentTree';
17 -import {setComponentTree} from './legacy-events/EventPluginUtils';
18 -import {receiveEvent, receiveTouches} from './ReactNativeEventEmitter';
19 -import ReactNativeGlobalResponderHandler from './ReactNativeGlobalResponderHandler';
20 -import ResponderEventPlugin from './legacy-events/ResponderEventPlugin';
21 -
22 -// Module provided by RN:
23 -import {RCTEventEmitter} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
24 -
25 -/**
26 - * Register the event emitter with the native bridge
27 - */
28 -RCTEventEmitter.register({
29 - receiveEvent,
30 - receiveTouches,
31 -});
32 -
33 -setComponentTree(
34 - getFiberCurrentPropsFromNode,
35 - getInstanceFromNode,
36 - getNodeFromInstance,
37 -);
38 -
39 -ResponderEventPlugin.injection.injectGlobalResponderHandler(
40 - ReactNativeGlobalResponderHandler,
41 -);
packages/react-native-renderer/src/ReactNativePublicCompat.js
+8 -64
@@ -13,8 +13,6 @@ import type {PublicInstance} from 'react-native/Libraries/ReactPrivate/ReactNati
13
14 // Modules provided by RN:
15 import {
16 - UIManager,
17 - legacySendAccessibilityEvent,
16 getNodeFromPublicInstance,
17 getNativeTagFromPublicInstance,
18 getInternalInstanceHandleFromPublicInstance,
@@ -65,13 +63,6 @@ export function findHostInstance_DEPRECATED<TElementType: ElementType>(
63 return componentOrHandle.canonical.publicInstance;
64 }
65
68 - // For compatibility with legacy renderer instances
69 - if (componentOrHandle._nativeTag) {
70 - // $FlowFixMe[incompatible-exact] Necessary when running Flow on Fabric
71 - // $FlowFixMe[incompatible-return]
72 - return componentOrHandle;
73 - }
74 -
66 let hostInstance;
67 if (__DEV__) {
68 hostInstance = findHostInstanceWithWarning(
@@ -116,11 +107,6 @@ export function findNodeHandle(componentOrHandle: any): ?number {
107 return componentOrHandle;
108 }
109
119 - // For compatibility with legacy renderer instances
120 - if (componentOrHandle._nativeTag) {
121 - return componentOrHandle._nativeTag;
122 - }
123 -
110 // For compatibility with Fabric instances
111 if (
112 componentOrHandle.canonical != null &&
@@ -150,11 +136,6 @@ export function findNodeHandle(componentOrHandle: any): ?number {
136 return hostInstance;
137 }
138
153 - if (hostInstance._nativeTag != null) {
154 - // $FlowFixMe[incompatible-return] For compatibility with legacy renderer instances
155 - return hostInstance._nativeTag;
156 - }
157 -
139 // $FlowFixMe[incompatible-call] Necessary when running Flow on the legacy renderer
140 return getNativeTagFromPublicInstance(hostInstance);
141 }
@@ -164,49 +145,32 @@ export function dispatchCommand(
145 command: string,
146 args: Array<any>,
147 ) {
167 - const nativeTag =
168 - handle._nativeTag != null
169 - ? handle._nativeTag
170 - : getNativeTagFromPublicInstance(handle);
171 - if (nativeTag == null) {
148 + const node = getNodeFromPublicInstance(handle);
149 +
150 + if (node != null) {
151 + nativeFabricUIManager.dispatchCommand(node, command, args);
152 + } else {
153 if (__DEV__) {
154 console.error(
155 "dispatchCommand was called with a ref that isn't a " +
156 'native component. Use React.forwardRef to get access to the underlying native component',
157 );
158 }
178 - return;
159 }
160 +}
161
162 +export function sendAccessibilityEvent(handle: any, eventType: string) {
163 const node = getNodeFromPublicInstance(handle);
164
165 if (node != null) {
184 - nativeFabricUIManager.dispatchCommand(node, command, args);
166 + nativeFabricUIManager.sendAccessibilityEvent(node, eventType);
167 } else {
186 - UIManager.dispatchViewManagerCommand(nativeTag, command, args);
187 - }
188 -}
189 -
190 -export function sendAccessibilityEvent(handle: any, eventType: string) {
191 - const nativeTag =
192 - handle._nativeTag != null
193 - ? handle._nativeTag
194 - : getNativeTagFromPublicInstance(handle);
195 - if (nativeTag == null) {
168 if (__DEV__) {
169 console.error(
170 "sendAccessibilityEvent was called with a ref that isn't a " +
171 'native component. Use React.forwardRef to get access to the underlying native component',
172 );
173 }
202 - return;
203 - }
204 -
205 - const node = getNodeFromPublicInstance(handle);
206 - if (node != null) {
207 - nativeFabricUIManager.sendAccessibilityEvent(node, eventType);
208 - } else {
209 - legacySendAccessibilityEvent(nativeTag, eventType);
174 }
175 }
176
@@ -223,29 +187,11 @@ export function getNodeFromInternalInstanceHandle(
187 );
188 }
189
226 -// Remove this once Paper is no longer supported and DOM Node API are enabled by default in RN.
190 export function isChildPublicInstance(
191 parentInstance: PublicInstance,
192 childInstance: PublicInstance,
193 ): boolean {
194 if (__DEV__) {
232 - // Paper
233 - if (
234 - // $FlowExpectedError[incompatible-type]
235 - // $FlowExpectedError[prop-missing] Don't check via `instanceof ReactNativeFiberHostComponent`, so it won't be leaked to Fabric.
236 - parentInstance._internalFiberInstanceHandleDEV &&
237 - // $FlowExpectedError[incompatible-type]
238 - // $FlowExpectedError[prop-missing] Don't check via `instanceof ReactNativeFiberHostComponent`, so it won't be leaked to Fabric.
239 - childInstance._internalFiberInstanceHandleDEV
240 - ) {
241 - return doesFiberContain(
242 - // $FlowExpectedError[incompatible-call]
243 - parentInstance._internalFiberInstanceHandleDEV,
244 - // $FlowExpectedError[incompatible-call]
245 - childInstance._internalFiberInstanceHandleDEV,
246 - );
247 - }
248 -
195 const parentInternalInstanceHandle =
196 // $FlowExpectedError[incompatible-call] Type for parentInstance should have been PublicInstance from ReactFiberConfigFabric.
197 getInternalInstanceHandleFromPublicInstance(parentInstance);
@@ -253,7 +199,6 @@ export function isChildPublicInstance(
199 // $FlowExpectedError[incompatible-call] Type for childInstance should have been PublicInstance from ReactFiberConfigFabric.
200 getInternalInstanceHandleFromPublicInstance(childInstance);
201
256 - // Fabric
202 if (
203 parentInternalInstanceHandle != null &&
204 childInternalInstanceHandle != null
@@ -264,7 +209,6 @@ export function isChildPublicInstance(
209 );
210 }
211
267 - // Means that one instance is from Fabric and other is from Paper.
212 return false;
213 } else {
214 throw new Error('isChildPublicInstance() is not available in production.');
packages/react-native-renderer/src/ReactNativeRenderer.js deleted
-223
@@ -1,223 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -import type {ReactPortal, ReactNodeList} from 'shared/ReactTypes';
11 -import type {ElementRef, ElementType, MixedElement} from 'react';
12 -import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
13 -import type {RenderRootOptions} from './ReactNativeTypes';
14 -import type {Container} from 'react-reconciler/src/ReactFiberConfig';
15 -
16 -import './ReactNativeInjection';
17 -
18 -import {
19 - batchedUpdates as batchedUpdatesImpl,
20 - discreteUpdates,
21 - createContainer,
22 - updateContainer,
23 - injectIntoDevTools,
24 - getPublicRootInstance,
25 - defaultOnUncaughtError,
26 - defaultOnCaughtError,
27 - defaultOnRecoverableError,
28 -} from 'react-reconciler/src/ReactFiberReconciler';
29 -// TODO: direct imports like some-package/src/* are bad. Fix me.
30 -import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal';
31 -import {
32 - setBatchingImplementation,
33 - batchedUpdates,
34 -} from './legacy-events/ReactGenericBatching';
35 -// Modules provided by RN:
36 -import {UIManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
37 -
38 -import {LegacyRoot} from 'react-reconciler/src/ReactRootTags';
39 -import {
40 - findHostInstance_DEPRECATED,
41 - findNodeHandle,
42 - dispatchCommand,
43 - sendAccessibilityEvent,
44 - isChildPublicInstance,
45 -} from './ReactNativePublicCompat';
46 -
47 -import {disableLegacyMode} from 'shared/ReactFeatureFlags';
48 -
49 -// Module provided by RN:
50 -import {ReactFiberErrorDialog} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
51 -
52 -import reactNativePackageVersion from 'shared/ReactVersion';
53 -import * as IsomorphicReactPackage from 'react';
54 -
55 -const isomorphicReactPackageVersion = IsomorphicReactPackage.version;
56 -if (isomorphicReactPackageVersion !== reactNativePackageVersion) {
57 - throw new Error(
58 - 'Incompatible React versions: The "react" and "react-native-renderer" packages must ' +
59 - 'have the exact same version. Instead got:\n' +
60 - ` - react: ${isomorphicReactPackageVersion}\n` +
61 - ` - react-native-renderer: ${reactNativePackageVersion}\n` +
62 - 'Learn more: https://react.dev/warnings/version-mismatch',
63 - );
64 -}
65 -
66 -if (typeof ReactFiberErrorDialog.showErrorDialog !== 'function') {
67 - throw new Error(
68 - 'Expected ReactFiberErrorDialog.showErrorDialog to be a function.',
69 - );
70 -}
71 -
72 -function nativeOnUncaughtError(
73 - error: mixed,
74 - errorInfo: {+componentStack?: ?string},
75 -): void {
76 - const componentStack =
77 - errorInfo.componentStack != null ? errorInfo.componentStack : '';
78 - const logError = ReactFiberErrorDialog.showErrorDialog({
79 - errorBoundary: null,
80 - error,
81 - componentStack,
82 - });
83 -
84 - // Allow injected showErrorDialog() to prevent default console.error logging.
85 - // This enables renderers like ReactNative to better manage redbox behavior.
86 - if (logError === false) {
87 - return;
88 - }
89 -
90 - defaultOnUncaughtError(error, errorInfo);
91 -}
92 -function nativeOnCaughtError(
93 - error: mixed,
94 - errorInfo: {
95 - +componentStack?: ?string,
96 - +errorBoundary?: ?component(...props: any),
97 - },
98 -): void {
99 - const errorBoundary = errorInfo.errorBoundary;
100 - const componentStack =
101 - errorInfo.componentStack != null ? errorInfo.componentStack : '';
102 - const logError = ReactFiberErrorDialog.showErrorDialog({
103 - errorBoundary,
104 - error,
105 - componentStack,
106 - });
107 -
108 - // Allow injected showErrorDialog() to prevent default console.error logging.
109 - // This enables renderers like ReactNative to better manage redbox behavior.
110 - if (logError === false) {
111 - return;
112 - }
113 -
114 - defaultOnCaughtError(error, errorInfo);
115 -}
116 -function nativeOnDefaultTransitionIndicator(): void | (() => void) {
117 - // Native doesn't have a default indicator.
118 -}
119 -
120 -function render(
121 - element: MixedElement,
122 - containerTag: number,
123 - callback: ?() => void,
124 - options: ?RenderRootOptions,
125 -): ?ElementRef<ElementType> {
126 - if (disableLegacyMode) {
127 - throw new Error('render: Unsupported Legacy Mode API.');
128 - }
129 -
130 - let root = roots.get(containerTag);
131 -
132 - if (!root) {
133 - // TODO: these defaults are for backwards compatibility.
134 - // Once RN implements these options internally,
135 - // we can remove the defaults and ReactFiberErrorDialog.
136 - let onUncaughtError = nativeOnUncaughtError;
137 - let onCaughtError = nativeOnCaughtError;
138 - let onRecoverableError = defaultOnRecoverableError;
139 -
140 - if (options && options.onUncaughtError !== undefined) {
141 - onUncaughtError = options.onUncaughtError;
142 - }
143 - if (options && options.onCaughtError !== undefined) {
144 - onCaughtError = options.onCaughtError;
145 - }
146 - if (options && options.onRecoverableError !== undefined) {
147 - onRecoverableError = options.onRecoverableError;
148 - }
149 -
150 - const rootInstance: Container = {
151 - containerTag,
152 - // $FlowExpectedError[incompatible-type] the legacy renderer does not use public root instances
153 - publicInstance: null,
154 - };
155 -
156 - // TODO (bvaughn): If we decide to keep the wrapper component,
157 - // We could create a wrapper for containerTag as well to reduce special casing.
158 - root = createContainer(
159 - rootInstance,
160 - LegacyRoot,
161 - null,
162 - false,
163 - null,
164 - '',
165 - onUncaughtError,
166 - onCaughtError,
167 - onRecoverableError,
168 - nativeOnDefaultTransitionIndicator,
169 - null,
170 - );
171 - roots.set(containerTag, root);
172 - }
173 - updateContainer(element, root, null, callback);
174 -
175 - return getPublicRootInstance(root);
176 -}
177 -
178 -function unmountComponentAtNode(containerTag: number) {
179 - const root = roots.get(containerTag);
180 - if (root) {
181 - // TODO: Is it safe to reset this now or should I wait since this unmount could be deferred?
182 - updateContainer(null, root, null, () => {
183 - roots.delete(containerTag);
184 - });
185 - }
186 -}
187 -
188 -function unmountComponentAtNodeAndRemoveContainer(containerTag: number) {
189 - unmountComponentAtNode(containerTag);
190 -
191 - // Call back into native to remove all of the subviews from this container
192 - UIManager.removeRootView(containerTag);
193 -}
194 -
195 -function createPortal(
196 - children: ReactNodeList,
197 - containerTag: number,
198 - key: ?string = null,
199 -): ReactPortal {
200 - return createPortalImpl(children, containerTag, null, key);
201 -}
202 -
203 -setBatchingImplementation(batchedUpdatesImpl, discreteUpdates);
204 -
205 -const roots = new Map<number, FiberRoot>();
206 -
207 -export {
208 - // This is needed for implementation details of TouchableNativeFeedback
209 - // Remove this once TouchableNativeFeedback doesn't use cloneElement
210 - findHostInstance_DEPRECATED,
211 - findNodeHandle,
212 - dispatchCommand,
213 - sendAccessibilityEvent,
214 - render,
215 - unmountComponentAtNode,
216 - unmountComponentAtNodeAndRemoveContainer,
217 - createPortal,
218 - batchedUpdates as unstable_batchedUpdates,
219 - // DEV-only:
220 - isChildPublicInstance,
221 -};
222 -
223 -injectIntoDevTools();
packages/react-native-renderer/src/ReactNativeTypes.js
-30
@@ -137,36 +137,6 @@ export type RenderRootOptions = {
137 onDefaultTransitionIndicator?: () => void | (() => void),
138 };
139
140 -/**
141 - * Flat ReactNative renderer bundles are too big for Flow to parse efficiently.
142 - * Provide minimal Flow typing for the high-level RN API and call it a day.
143 - */
144 -export type ReactNativeType = {
145 - findHostInstance_DEPRECATED<TElementType: React.ElementType>(
146 - componentOrHandle: ?(React.ElementRef<TElementType> | number),
147 - ): ?PublicInstance,
148 - findNodeHandle<TElementType: React.ElementType>(
149 - componentOrHandle: ?(React.ElementRef<TElementType> | number),
150 - ): ?number,
151 - isChildPublicInstance(parent: PublicInstance, child: PublicInstance): boolean,
152 - dispatchCommand(
153 - handle: PublicInstance,
154 - command: string,
155 - args: Array<mixed>,
156 - ): void,
157 - sendAccessibilityEvent(handle: PublicInstance, eventType: string): void,
158 - render(
159 - element: React.MixedElement,
160 - containerTag: number,
161 - callback: ?() => void,
162 - options: ?RenderRootOptions,
163 - ): ?React.ElementRef<React.ElementType>,
164 - unmountComponentAtNode(containerTag: number): void,
165 - unmountComponentAtNodeAndRemoveContainer(containerTag: number): void,
166 - +unstable_batchedUpdates: <T>(fn: (T) => void, bookkeeping: T) => void,
167 - ...
168 -};
169 -
140 export opaque type Node = mixed;
141 export opaque type InternalInstanceHandle = mixed;
142
packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/BatchedBridge.js deleted
-14
@@ -1,14 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - */
7 -
8 -'use strict';
9 -
10 -const BatchedBridge = {
11 - registerCallableModule: jest.fn(),
12 -};
13 -
14 -module.exports = BatchedBridge;
packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ExceptionsManager.js deleted
-12
@@ -1,12 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - */
7 -
8 -'use strict';
9 -
10 -module.exports = {
11 - handleException: jest.fn(),
12 -};
packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/Platform.js deleted
-11
@@ -1,11 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - */
7 -'use strict';
8 -
9 -module.exports = {
10 - OS: 'ios',
11 -};
packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/RCTEventEmitter.js deleted
-14
@@ -1,14 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - */
7 -
8 -'use strict';
9 -
10 -const RCTEventEmitter = {
11 - register: jest.fn(),
12 -};
13 -
14 -module.exports = RCTEventEmitter;
packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativePrivateInterface.js
-24
@@ -8,39 +8,15 @@
8 */
9
10 module.exports = {
11 - get BatchedBridge() {
12 - return require('./BatchedBridge.js');
13 - },
14 - get Platform() {
15 - return require('./Platform');
16 - },
17 - get RCTEventEmitter() {
18 - return require('./RCTEventEmitter');
19 - },
11 get ReactFiberErrorDialog() {
12 return require('./ReactFiberErrorDialog');
13 },
14 get ReactNativeViewConfigRegistry() {
15 return require('./ReactNativeViewConfigRegistry');
16 },
26 - get TextInputState() {
27 - return require('./TextInputState');
28 - },
29 - get UIManager() {
30 - return require('./UIManager');
31 - },
32 - get deepDiffer() {
33 - return require('./deepDiffer');
34 - },
17 get deepFreezeAndThrowOnMutationInDev() {
18 return require('./deepFreezeAndThrowOnMutationInDev');
19 },
38 - get flattenStyle() {
39 - return require('./flattenStyle');
40 - },
41 - get legacySendAccessibilityEvent() {
42 - return require('./legacySendAccessibilityEvent');
43 - },
20 get RawEventEmitter() {
21 return require('./RawEventEmitter').default;
22 },
packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/TextInputState.js deleted
-18
@@ -1,18 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - */
7 -
8 -'use strict';
9 -
10 -// Mock of the Native Hooks
11 -// TODO: Should this move into the components themselves? E.g. focusable
12 -
13 -const TextInputState = {
14 - blurTextInput: jest.fn(),
15 - focusTextInput: jest.fn(),
16 -};
17 -
18 -module.exports = TextInputState;
packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/UIManager.js deleted
-194
@@ -1,194 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - */
7 -
8 -'use strict';
9 -
10 -// Mock of the Native Hooks
11 -
12 -// Map of viewTag -> {children: [childTag], parent: ?parentTag}
13 -const roots = [];
14 -const views = new Map();
15 -
16 -function autoCreateRoot(tag) {
17 - // Seriously, this is how we distinguish roots in RN.
18 - if (!views.has(tag) && tag % 10 === 1) {
19 - roots.push(tag);
20 - views.set(tag, {
21 - children: [],
22 - parent: null,
23 - props: {},
24 - viewName: '<native root>',
25 - });
26 - }
27 -}
28 -
29 -function insertSubviewAtIndex(parent, child, index) {
30 - const parentInfo = views.get(parent);
31 - const childInfo = views.get(child);
32 -
33 - if (childInfo.parent !== null) {
34 - throw new Error(
35 - `Inserting view ${child} ${JSON.stringify(
36 - childInfo.props,
37 - )} which already has parent`,
38 - );
39 - }
40 -
41 - if (0 > index || index > parentInfo.children.length) {
42 - throw new Error(
43 - `Invalid index ${index} for children ${parentInfo.children}`,
44 - );
45 - }
46 -
47 - parentInfo.children.splice(index, 0, child);
48 - childInfo.parent = parent;
49 -}
50 -
51 -function removeChild(parent, child) {
52 - const parentInfo = views.get(parent);
53 - const childInfo = views.get(child);
54 - const index = parentInfo.children.indexOf(child);
55 -
56 - if (index < 0) {
57 - throw new Error(`Missing view ${child} during removal`);
58 - }
59 -
60 - parentInfo.children.splice(index, 1);
61 - childInfo.parent = null;
62 -}
63 -
64 -const RCTUIManager = {
65 - __dumpHierarchyForJestTestsOnly: function () {
66 - function dumpSubtree(tag, indent) {
67 - const info = views.get(tag);
68 - let out = '';
69 - out +=
70 - ' '.repeat(indent) + info.viewName + ' ' + JSON.stringify(info.props);
71 - // eslint-disable-next-line no-for-of-loops/no-for-of-loops
72 - for (const child of info.children) {
73 - out += '\n' + dumpSubtree(child, indent + 2);
74 - }
75 - return out;
76 - }
77 - return roots.map(tag => dumpSubtree(tag, 0)).join('\n');
78 - },
79 - clearJSResponder: jest.fn(),
80 - createView: jest.fn(function createView(reactTag, viewName, rootTag, props) {
81 - if (views.has(reactTag)) {
82 - throw new Error(`Created two native views with tag ${reactTag}`);
83 - }
84 -
85 - views.set(reactTag, {
86 - children: [],
87 - parent: null,
88 - props: props,
89 - viewName: viewName,
90 - });
91 - }),
92 - dispatchViewManagerCommand: jest.fn(),
93 - sendAccessibilityEvent: jest.fn(),
94 - setJSResponder: jest.fn(),
95 - setChildren: jest.fn(function setChildren(parentTag, reactTags) {
96 - autoCreateRoot(parentTag);
97 -
98 - // Native doesn't actually check this but it seems like a good idea
99 - if (views.get(parentTag).children.length !== 0) {
100 - throw new Error(`Calling .setChildren on nonempty view ${parentTag}`);
101 - }
102 -
103 - // This logic ported from iOS (RCTUIManager.m)
104 - reactTags.forEach((tag, i) => {
105 - insertSubviewAtIndex(parentTag, tag, i);
106 - });
107 - }),
108 - manageChildren: jest.fn(function manageChildren(
109 - parentTag,
110 - moveFromIndices = [],
111 - moveToIndices = [],
112 - addChildReactTags = [],
113 - addAtIndices = [],
114 - removeAtIndices = [],
115 - ) {
116 - autoCreateRoot(parentTag);
117 -
118 - // This logic ported from iOS (RCTUIManager.m)
119 - if (moveFromIndices.length !== moveToIndices.length) {
120 - throw new Error(
121 - `Mismatched move indices ${moveFromIndices} and ${moveToIndices}`,
122 - );
123 - }
124 -
125 - if (addChildReactTags.length !== addAtIndices.length) {
126 - throw new Error(
127 - `Mismatched add indices ${addChildReactTags} and ${addAtIndices}`,
128 - );
129 - }
130 -
131 - const parentInfo = views.get(parentTag);
132 - const permanentlyRemovedChildren = removeAtIndices.map(
133 - index => parentInfo.children[index],
134 - );
135 - const temporarilyRemovedChildren = moveFromIndices.map(
136 - index => parentInfo.children[index],
137 - );
138 - permanentlyRemovedChildren.forEach(tag => removeChild(parentTag, tag));
139 - temporarilyRemovedChildren.forEach(tag => removeChild(parentTag, tag));
140 - permanentlyRemovedChildren.forEach(tag => {
141 - views.delete(tag);
142 - });
143 - // List of [index, tag]
144 - const indicesToInsert = [];
145 - temporarilyRemovedChildren.forEach((tag, i) => {
146 - indicesToInsert.push([moveToIndices[i], temporarilyRemovedChildren[i]]);
147 - });
148 - addChildReactTags.forEach((tag, i) => {
149 - indicesToInsert.push([addAtIndices[i], addChildReactTags[i]]);
150 - });
151 - indicesToInsert.sort((a, b) => a[0] - b[0]);
152 - // eslint-disable-next-line no-for-of-loops/no-for-of-loops
153 - for (const [i, tag] of indicesToInsert) {
154 - insertSubviewAtIndex(parentTag, tag, i);
155 - }
156 - }),
157 - updateView: jest.fn(),
158 - removeSubviewsFromContainerWithID: jest.fn(function (parentTag) {
159 - views.get(parentTag).children.forEach(tag => removeChild(parentTag, tag));
160 - }),
161 - replaceExistingNonRootView: jest.fn(),
162 - measure: jest.fn(function measure(tag, callback) {
163 - if (typeof tag !== 'number') {
164 - throw new Error(`Expected tag to be a number, was passed ${tag}`);
165 - }
166 -
167 - callback(10, 10, 100, 100, 0, 0);
168 - }),
169 - measureInWindow: jest.fn(function measureInWindow(tag, callback) {
170 - if (typeof tag !== 'number') {
171 - throw new Error(`Expected tag to be a number, was passed ${tag}`);
172 - }
173 -
174 - callback(10, 10, 100, 100);
175 - }),
176 - measureLayout: jest.fn(
177 - function measureLayout(tag, relativeTag, fail, success) {
178 - if (typeof tag !== 'number') {
179 - throw new Error(`Expected tag to be a number, was passed ${tag}`);
180 - }
181 -
182 - if (typeof relativeTag !== 'number') {
183 - throw new Error(
184 - `Expected relativeTag to be a number, was passed ${relativeTag}`,
185 - );
186 - }
187 -
188 - success(1, 1, 100, 100);
189 - },
190 - ),
191 - __takeSnapshot: jest.fn(),
192 -};
193 -
194 -module.exports = RCTUIManager;
packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/flattenStyle.js deleted
-14
@@ -1,14 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - */
7 -
8 -'use strict';
9 -
10 -// TODO: Move flattenStyle into react
11 -
12 -function flattenStyle() {}
13 -
14 -module.exports = flattenStyle;
packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/legacySendAccessibilityEvent.js deleted
-10
@@ -1,10 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - */
7 -
8 -'use strict';
9 -
10 -module.exports = jest.fn();
packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js
+4
@@ -1521,6 +1521,10 @@ describe('ReactFabric', () => {
1521 dangerouslyRetainedViewRef,
1522 'eventTypeName',
1523 );
1524 + assertConsoleErrorDev([
1525 + "sendAccessibilityEvent was called with a ref that isn't a " +
1526 + 'native component. Use React.forwardRef to get access to the underlying native component',
1527 + ]);
1528
1529 expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled();
1530 });
packages/react-native-renderer/src/__tests__/ReactFabricAndNative-test.internal.js deleted
-231
@@ -1,231 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @emails react-core
8 - * @jest-environment node
9 - */
10 -
11 -'use strict';
12 -
13 -let React;
14 -let ReactFabric;
15 -let ReactNative;
16 -let UIManager;
17 -let createReactNativeComponentClass;
18 -let ReactNativePrivateInterface;
19 -let getNativeTagFromPublicInstance;
20 -
21 -describe('created with ReactFabric called with ReactNative', () => {
22 - beforeEach(() => {
23 - jest.resetModules();
24 - require('react-native/Libraries/ReactPrivate/InitializeNativeFabricUIManager');
25 - ReactNative = require('react-native-renderer');
26 - jest.resetModules();
27 - ReactNativePrivateInterface = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface');
28 - UIManager =
29 - require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface').UIManager;
30 - jest.mock('shared/ReactFeatureFlags', () =>
31 - require('shared/forks/ReactFeatureFlags.native-oss'),
32 - );
33 -
34 - React = require('react');
35 - ReactFabric = require('react-native-renderer/fabric');
36 - createReactNativeComponentClass =
37 - require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
38 - .ReactNativeViewConfigRegistry.register;
39 - getNativeTagFromPublicInstance =
40 - require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface').getNativeTagFromPublicInstance;
41 - });
42 -
43 - it('find Fabric instances with the RN renderer', () => {
44 - const View = createReactNativeComponentClass('RCTView', () => ({
45 - validAttributes: {title: true},
46 - uiViewClassName: 'RCTView',
47 - }));
48 -
49 - const ref = React.createRef();
50 -
51 - class Component extends React.Component {
52 - render() {
53 - return <View title="foo" />;
54 - }
55 - }
56 -
57 - ReactFabric.render(<Component ref={ref} />, 11);
58 -
59 - const instance = ReactNative.findHostInstance_DEPRECATED(ref.current);
60 - expect(getNativeTagFromPublicInstance(instance)).toBe(2);
61 - });
62 -
63 - it('find Fabric nodes with the RN renderer', () => {
64 - const View = createReactNativeComponentClass('RCTView', () => ({
65 - validAttributes: {title: true},
66 - uiViewClassName: 'RCTView',
67 - }));
68 -
69 - const ref = React.createRef();
70 -
71 - class Component extends React.Component {
72 - render() {
73 - return <View title="foo" />;
74 - }
75 - }
76 -
77 - ReactFabric.render(<Component ref={ref} />, 11);
78 -
79 - const handle = ReactNative.findNodeHandle(ref.current);
80 - expect(handle).toBe(2);
81 - });
82 -
83 - it('dispatches commands on Fabric nodes with the RN renderer', () => {
84 - nativeFabricUIManager.dispatchCommand.mockClear();
85 - const View = createReactNativeComponentClass('RCTView', () => ({
86 - validAttributes: {title: true},
87 - uiViewClassName: 'RCTView',
88 - }));
89 -
90 - const ref = React.createRef();
91 -
92 - ReactFabric.render(<View title="bar" ref={ref} />, 11);
93 - expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
94 - ReactNative.dispatchCommand(ref.current, 'myCommand', [10, 20]);
95 - expect(nativeFabricUIManager.dispatchCommand).toHaveBeenCalledTimes(1);
96 - expect(nativeFabricUIManager.dispatchCommand).toHaveBeenCalledWith(
97 - expect.any(Object),
98 - 'myCommand',
99 - [10, 20],
100 - );
101 - expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
102 - });
103 -
104 - it('dispatches sendAccessibilityEvent on Fabric nodes with the RN renderer', () => {
105 - nativeFabricUIManager.sendAccessibilityEvent.mockClear();
106 - const View = createReactNativeComponentClass('RCTView', () => ({
107 - validAttributes: {title: true},
108 - uiViewClassName: 'RCTView',
109 - }));
110 -
111 - const ref = React.createRef();
112 -
113 - ReactFabric.render(<View title="bar" ref={ref} />, 11);
114 - expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled();
115 - ReactNative.sendAccessibilityEvent(ref.current, 'focus');
116 - expect(nativeFabricUIManager.sendAccessibilityEvent).toHaveBeenCalledTimes(
117 - 1,
118 - );
119 - expect(nativeFabricUIManager.sendAccessibilityEvent).toHaveBeenCalledWith(
120 - expect.any(Object),
121 - 'focus',
122 - );
123 - expect(UIManager.sendAccessibilityEvent).not.toBeCalled();
124 - });
125 -});
126 -
127 -describe('created with ReactNative called with ReactFabric', () => {
128 - beforeEach(() => {
129 - jest.resetModules();
130 - require('react-native/Libraries/ReactPrivate/InitializeNativeFabricUIManager');
131 - ReactFabric = require('react-native-renderer/fabric');
132 - jest.resetModules();
133 - UIManager =
134 - require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface').UIManager;
135 - jest.mock('shared/ReactFeatureFlags', () =>
136 - require('shared/forks/ReactFeatureFlags.native-oss'),
137 - );
138 - ReactNative = require('react-native-renderer');
139 -
140 - React = require('react');
141 - createReactNativeComponentClass =
142 - require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
143 - .ReactNativeViewConfigRegistry.register;
144 - });
145 -
146 - it('find Paper instances with the Fabric renderer', () => {
147 - const View = createReactNativeComponentClass('RCTView', () => ({
148 - validAttributes: {title: true},
149 - uiViewClassName: 'RCTView',
150 - }));
151 -
152 - const ref = React.createRef();
153 -
154 - class Component extends React.Component {
155 - render() {
156 - return <View title="foo" />;
157 - }
158 - }
159 -
160 - ReactNative.render(<Component ref={ref} />, 11);
161 -
162 - const instance = ReactFabric.findHostInstance_DEPRECATED(ref.current);
163 - expect(instance._nativeTag).toBe(3);
164 - });
165 -
166 - it('find Paper nodes with the Fabric renderer', () => {
167 - const View = createReactNativeComponentClass('RCTView', () => ({
168 - validAttributes: {title: true},
169 - uiViewClassName: 'RCTView',
170 - }));
171 -
172 - const ref = React.createRef();
173 -
174 - class Component extends React.Component {
175 - render() {
176 - return <View title="foo" />;
177 - }
178 - }
179 -
180 - ReactNative.render(<Component ref={ref} />, 11);
181 -
182 - const handle = ReactFabric.findNodeHandle(ref.current);
183 - expect(handle).toBe(3);
184 - });
185 -
186 - it('dispatches commands on Paper nodes with the Fabric renderer', () => {
187 - UIManager.dispatchViewManagerCommand.mockReset();
188 - const View = createReactNativeComponentClass('RCTView', () => ({
189 - validAttributes: {title: true},
190 - uiViewClassName: 'RCTView',
191 - }));
192 -
193 - const ref = React.createRef();
194 -
195 - ReactNative.render(<View title="bar" ref={ref} />, 11);
196 - expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
197 - ReactFabric.dispatchCommand(ref.current, 'myCommand', [10, 20]);
198 - expect(UIManager.dispatchViewManagerCommand).toHaveBeenCalledTimes(1);
199 - expect(UIManager.dispatchViewManagerCommand).toHaveBeenCalledWith(
200 - expect.any(Number),
201 - 'myCommand',
202 - [10, 20],
203 - );
204 -
205 - expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
206 - });
207 -
208 - it('dispatches sendAccessibilityEvent on Paper nodes with the Fabric renderer', () => {
209 - ReactNativePrivateInterface.legacySendAccessibilityEvent.mockReset();
210 - const View = createReactNativeComponentClass('RCTView', () => ({
211 - validAttributes: {title: true},
212 - uiViewClassName: 'RCTView',
213 - }));
214 -
215 - const ref = React.createRef();
216 -
217 - ReactNative.render(<View title="bar" ref={ref} />, 11);
218 - expect(
219 - ReactNativePrivateInterface.legacySendAccessibilityEvent,
220 - ).not.toBeCalled();
221 - ReactFabric.sendAccessibilityEvent(ref.current, 'focus');
222 - expect(
223 - ReactNativePrivateInterface.legacySendAccessibilityEvent,
224 - ).toHaveBeenCalledTimes(1);
225 - expect(
226 - ReactNativePrivateInterface.legacySendAccessibilityEvent,
227 - ).toHaveBeenCalledWith(expect.any(Number), 'focus');
228 -
229 - expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled();
230 - });
231 -});
packages/react-native-renderer/src/__tests__/ReactNativeAttributePayload-test.internal.js deleted
-287
@@ -1,287 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @jest-environment node
8 - */
9 -'use strict';
10 -
11 -const ReactNativeAttributePayload = require('../ReactNativeAttributePayload');
12 -
13 -const diff = ReactNativeAttributePayload.diff;
14 -
15 -describe('ReactNativeAttributePayload', () => {
16 - it('should work with simple example', () => {
17 - expect(diff({a: 1, c: 3}, {b: 2, c: 3}, {a: true, b: true})).toEqual({
18 - a: null,
19 - b: 2,
20 - });
21 - });
22 -
23 - it('should skip fields that are equal', () => {
24 - expect(
25 - diff(
26 - {a: 1, b: 'two', c: true, d: false, e: undefined, f: 0},
27 - {a: 1, b: 'two', c: true, d: false, e: undefined, f: 0},
28 - {a: true, b: true, c: true, d: true, e: true, f: true},
29 - ),
30 - ).toEqual(null);
31 - });
32 -
33 - it('should remove fields', () => {
34 - expect(diff({a: 1}, {}, {a: true})).toEqual({a: null});
35 - });
36 -
37 - it('should remove fields that are set to undefined', () => {
38 - expect(diff({a: 1}, {a: undefined}, {a: true})).toEqual({a: null});
39 - });
40 -
41 - it('should ignore invalid fields', () => {
42 - expect(diff({a: 1}, {b: 2}, {})).toEqual(null);
43 - });
44 -
45 - it('should use the diff attribute', () => {
46 - const diffA = jest.fn((a, b) => true);
47 - const diffB = jest.fn((a, b) => false);
48 - expect(
49 - diff(
50 - {a: [1], b: [3]},
51 - {a: [2], b: [4]},
52 - {a: {diff: diffA}, b: {diff: diffB}},
53 - ),
54 - ).toEqual({a: [2]});
55 - expect(diffA).toBeCalledWith([1], [2]);
56 - expect(diffB).toBeCalledWith([3], [4]);
57 - });
58 -
59 - it('should not use the diff attribute on addition/removal', () => {
60 - const diffA = jest.fn();
61 - const diffB = jest.fn();
62 - expect(
63 - diff({a: [1]}, {b: [2]}, {a: {diff: diffA}, b: {diff: diffB}}),
64 - ).toEqual({a: null, b: [2]});
65 - expect(diffA).not.toBeCalled();
66 - expect(diffB).not.toBeCalled();
67 - });
68 -
69 - it('should do deep diffs of Objects by default', () => {
70 - expect(
71 - diff(
72 - {a: [1], b: {k: [3, 4]}, c: {k: [4, 4]}},
73 - {a: [2], b: {k: [3, 4]}, c: {k: [4, 5]}},
74 - {a: true, b: true, c: true},
75 - ),
76 - ).toEqual({a: [2], c: {k: [4, 5]}});
77 - });
78 -
79 - it('should work with undefined styles', () => {
80 - expect(
81 - diff(
82 - {style: {a: '#ffffff', b: 1}},
83 - {style: undefined},
84 - {style: {b: true}},
85 - ),
86 - ).toEqual({b: null});
87 - expect(
88 - diff(
89 - {style: undefined},
90 - {style: {a: '#ffffff', b: 1}},
91 - {style: {b: true}},
92 - ),
93 - ).toEqual({b: 1});
94 - expect(
95 - diff({style: undefined}, {style: undefined}, {style: {b: true}}),
96 - ).toEqual(null);
97 - });
98 -
99 - it('should work with empty styles', () => {
100 - expect(diff({a: 1, c: 3}, {}, {a: true, b: true})).toEqual({a: null});
101 - expect(diff({}, {a: 1, c: 3}, {a: true, b: true})).toEqual({a: 1});
102 - expect(diff({}, {}, {a: true, b: true})).toEqual(null);
103 - });
104 -
105 - it('should flatten nested styles and predefined styles', () => {
106 - const validStyleAttribute = {someStyle: {foo: true, bar: true}};
107 -
108 - expect(
109 - diff({}, {someStyle: [{foo: 1}, {bar: 2}]}, validStyleAttribute),
110 - ).toEqual({foo: 1, bar: 2});
111 -
112 - expect(
113 - diff({someStyle: [{foo: 1}, {bar: 2}]}, {}, validStyleAttribute),
114 - ).toEqual({foo: null, bar: null});
115 -
116 - const barStyle = {
117 - bar: 3,
118 - };
119 -
120 - expect(
121 - diff(
122 - {},
123 - {someStyle: [[{foo: 1}, {foo: 2}], barStyle]},
124 - validStyleAttribute,
125 - ),
126 - ).toEqual({foo: 2, bar: 3});
127 - });
128 -
129 - it('should reset a value to a previous if it is removed', () => {
130 - const validStyleAttribute = {someStyle: {foo: true, bar: true}};
131 -
132 - expect(
133 - diff(
134 - {someStyle: [{foo: 1}, {foo: 3}]},
135 - {someStyle: [{foo: 1}, {bar: 2}]},
136 - validStyleAttribute,
137 - ),
138 - ).toEqual({foo: 1, bar: 2});
139 - });
140 -
141 - it('should not clear removed props if they are still in another slot', () => {
142 - const validStyleAttribute = {someStyle: {foo: true, bar: true}};
143 -
144 - expect(
145 - diff(
146 - {someStyle: [{}, {foo: 3, bar: 2}]},
147 - {someStyle: [{foo: 3}, {bar: 2}]},
148 - validStyleAttribute,
149 - ),
150 - ).toEqual({foo: 3}); // this should ideally be null. heuristic tradeoff.
151 -
152 - expect(
153 - diff(
154 - {someStyle: [{}, {foo: 3, bar: 2}]},
155 - {someStyle: [{foo: 1, bar: 1}, {bar: 2}]},
156 - validStyleAttribute,
157 - ),
158 - ).toEqual({bar: 2, foo: 1});
159 - });
160 -
161 - it('should clear a prop if a later style is explicit null/undefined', () => {
162 - const validStyleAttribute = {someStyle: {foo: true, bar: true}};
163 - expect(
164 - diff(
165 - {someStyle: [{}, {foo: 3, bar: 2}]},
166 - {someStyle: [{foo: 1}, {bar: 2, foo: null}]},
167 - validStyleAttribute,
168 - ),
169 - ).toEqual({foo: null});
170 -
171 - expect(
172 - diff(
173 - {someStyle: [{foo: 3}, {foo: null, bar: 2}]},
174 - {someStyle: [{foo: null}, {bar: 2}]},
175 - validStyleAttribute,
176 - ),
177 - ).toEqual({foo: null});
178 -
179 - expect(
180 - diff(
181 - {someStyle: [{foo: 1}, {foo: null}]},
182 - {someStyle: [{foo: 2}, {foo: null}]},
183 - validStyleAttribute,
184 - ),
185 - ).toEqual({foo: null}); // this should ideally be null. heuristic.
186 -
187 - // Test the same case with object equality because an early bailout doesn't
188 - // work in this case.
189 - const fooObj = {foo: 3};
190 - expect(
191 - diff(
192 - {someStyle: [{foo: 1}, fooObj]},
193 - {someStyle: [{foo: 2}, fooObj]},
194 - validStyleAttribute,
195 - ),
196 - ).toEqual({foo: 3}); // this should ideally be null. heuristic.
197 -
198 - expect(
199 - diff(
200 - {someStyle: [{foo: 1}, {foo: 3}]},
201 - {someStyle: [{foo: 2}, {foo: undefined}]},
202 - validStyleAttribute,
203 - ),
204 - ).toEqual({foo: null}); // this should ideally be null. heuristic.
205 - });
206 -
207 - it('handles attributes defined multiple times', () => {
208 - const validAttributes = {foo: true, style: {foo: true}};
209 - expect(diff({}, {foo: 4, style: {foo: 2}}, validAttributes)).toEqual({
210 - foo: 2,
211 - });
212 - expect(diff({foo: 4}, {style: {foo: 2}}, validAttributes)).toEqual({
213 - foo: 2,
214 - });
215 - expect(diff({style: {foo: 2}}, {foo: 4}, validAttributes)).toEqual({
216 - foo: 4,
217 - });
218 - });
219 -
220 - // Function properties are just markers to native that events should be sent.
221 - it('should convert functions to booleans', () => {
222 - // Note that if the property changes from one function to another, we don't
223 - // need to send an update.
224 - expect(
225 - diff(
226 - {
227 - a: function () {
228 - return 1;
229 - },
230 - b: function () {
231 - return 2;
232 - },
233 - c: 3,
234 - },
235 - {
236 - b: function () {
237 - return 9;
238 - },
239 - c: function () {
240 - return 3;
241 - },
242 - },
243 - {a: true, b: true, c: true},
244 - ),
245 - ).toEqual({a: null, c: true});
246 - });
247 -
248 - it('should skip changed functions', () => {
249 - expect(
250 - diff(
251 - {
252 - a: function () {
253 - return 1;
254 - },
255 - },
256 - {
257 - a: function () {
258 - return 9;
259 - },
260 - },
261 - {a: true},
262 - ),
263 - ).toEqual(null);
264 - });
265 -
266 - it('should skip deeply-nested changed functions', () => {
267 - expect(
268 - diff(
269 - {
270 - wrapper: {
271 - a: function () {
272 - return 1;
273 - },
274 - },
275 - },
276 - {
277 - wrapper: {
278 - a: function () {
279 - return 9;
280 - },
281 - },
282 - },
283 - {wrapper: true},
284 - ),
285 - ).toEqual(null);
286 - });
287 -});
packages/react-native-renderer/src/__tests__/ReactNativeEvents-test.internal.js deleted
-554
@@ -1,554 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @emails react-core
8 - * @jest-environment node
9 - */
10 -
11 -'use strict';
12 -
13 -let PropTypes;
14 -let RCTEventEmitter;
15 -let React;
16 -let act;
17 -let ReactNative;
18 -let ResponderEventPlugin;
19 -let UIManager;
20 -let createReactNativeComponentClass;
21 -let assertConsoleErrorDev;
22 -
23 -// Parallels requireNativeComponent() in that it lazily constructs a view config,
24 -// And registers view manager event types with ReactNativeViewConfigRegistry.
25 -const fakeRequireNativeComponent = (uiViewClassName, validAttributes) => {
26 - const getViewConfig = () => {
27 - const viewConfig = {
28 - uiViewClassName,
29 - validAttributes,
30 - bubblingEventTypes: {
31 - topTouchCancel: {
32 - phasedRegistrationNames: {
33 - bubbled: 'onTouchCancel',
34 - captured: 'onTouchCancelCapture',
35 - },
36 - },
37 - topTouchEnd: {
38 - phasedRegistrationNames: {
39 - bubbled: 'onTouchEnd',
40 - captured: 'onTouchEndCapture',
41 - },
42 - },
43 - topTouchMove: {
44 - phasedRegistrationNames: {
45 - bubbled: 'onTouchMove',
46 - captured: 'onTouchMoveCapture',
47 - },
48 - },
49 - topTouchStart: {
50 - phasedRegistrationNames: {
51 - bubbled: 'onTouchStart',
52 - captured: 'onTouchStartCapture',
53 - },
54 - },
55 - },
56 - directEventTypes: {},
57 - };
58 -
59 - return viewConfig;
60 - };
61 -
62 - return createReactNativeComponentClass(uiViewClassName, getViewConfig);
63 -};
64 -
65 -beforeEach(() => {
66 - jest.resetModules();
67 -
68 - PropTypes = require('prop-types');
69 - RCTEventEmitter =
70 - require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface').RCTEventEmitter;
71 - React = require('react');
72 - act = require('internal-test-utils').act;
73 - assertConsoleErrorDev = require('internal-test-utils').assertConsoleErrorDev;
74 - ReactNative = require('react-native-renderer');
75 - ResponderEventPlugin =
76 - require('react-native-renderer/src/legacy-events/ResponderEventPlugin').default;
77 - UIManager =
78 - require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface').UIManager;
79 - createReactNativeComponentClass =
80 - require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
81 - .ReactNativeViewConfigRegistry.register;
82 -});
83 -
84 -// @gate !disableLegacyMode
85 -test('fails to register the same event name with different types', async () => {
86 - const InvalidEvents = createReactNativeComponentClass('InvalidEvents', () => {
87 - if (!__DEV__) {
88 - // Simulate a registration error in prod.
89 - throw new Error('Event cannot be both direct and bubbling: topChange');
90 - }
91 -
92 - // This view config has the same bubbling and direct event name
93 - // which will fail to register in development.
94 - return {
95 - uiViewClassName: 'InvalidEvents',
96 - validAttributes: {
97 - onChange: true,
98 - },
99 - bubblingEventTypes: {
100 - topChange: {
101 - phasedRegistrationNames: {
102 - bubbled: 'onChange',
103 - captured: 'onChangeCapture',
104 - },
105 - },
106 - },
107 - directEventTypes: {
108 - topChange: {
109 - registrationName: 'onChange',
110 - },
111 - },
112 - };
113 - });
114 -
115 - // The first time this renders,
116 - // we attempt to register the view config and fail.
117 - await expect(
118 - async () => await act(() => ReactNative.render(<InvalidEvents />, 1)),
119 - ).rejects.toThrow('Event cannot be both direct and bubbling: topChange');
120 -
121 - // Continue to re-register the config and
122 - // fail so that we don't mask the above failure.
123 - await expect(
124 - async () => await act(() => ReactNative.render(<InvalidEvents />, 1)),
125 - ).rejects.toThrow('Event cannot be both direct and bubbling: topChange');
126 -});
127 -
128 -// @gate !disableLegacyMode
129 -test('fails if unknown/unsupported event types are dispatched', () => {
130 - expect(RCTEventEmitter.register).toHaveBeenCalledTimes(1);
131 - const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
132 - const View = fakeRequireNativeComponent('View', {});
133 -
134 - ReactNative.render(<View onUnspecifiedEvent={() => {}} />, 1);
135 -
136 - expect(UIManager.__dumpHierarchyForJestTestsOnly()).toMatchInlineSnapshot(`
137 - "<native root> {}
138 - View null"
139 - `);
140 - expect(UIManager.createView).toHaveBeenCalledTimes(1);
141 -
142 - const target = UIManager.createView.mock.calls[0][0];
143 -
144 - expect(() => {
145 - EventEmitter.receiveTouches(
146 - 'unspecifiedEvent',
147 - [{target, identifier: 17}],
148 - [0],
149 - );
150 - }).toThrow('Unsupported top level event type "unspecifiedEvent" dispatched');
151 -});
152 -
153 -// @gate !disableLegacyMode
154 -test('handles events', () => {
155 - expect(RCTEventEmitter.register).toHaveBeenCalledTimes(1);
156 - const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
157 - const View = fakeRequireNativeComponent('View', {foo: true});
158 -
159 - const log = [];
160 - ReactNative.render(
161 - <View
162 - foo="outer"
163 - onTouchEnd={() => log.push('outer touchend')}
164 - onTouchEndCapture={() => log.push('outer touchend capture')}
165 - onTouchStart={() => log.push('outer touchstart')}
166 - onTouchStartCapture={() => log.push('outer touchstart capture')}>
167 - <View
168 - foo="inner"
169 - onTouchEndCapture={() => log.push('inner touchend capture')}
170 - onTouchEnd={() => log.push('inner touchend')}
171 - onTouchStartCapture={() => log.push('inner touchstart capture')}
172 - onTouchStart={() => log.push('inner touchstart')}
173 - />
174 - </View>,
175 - 1,
176 - );
177 -
178 - expect(UIManager.__dumpHierarchyForJestTestsOnly()).toMatchInlineSnapshot(`
179 - "<native root> {}
180 - View {"foo":"outer"}
181 - View {"foo":"inner"}"
182 - `);
183 - expect(UIManager.createView).toHaveBeenCalledTimes(2);
184 -
185 - // Don't depend on the order of createView() calls.
186 - // Stack creates views outside-in; fiber creates them inside-out.
187 - const innerTag = UIManager.createView.mock.calls.find(
188 - args => args[3].foo === 'inner',
189 - )[0];
190 -
191 - EventEmitter.receiveTouches(
192 - 'topTouchStart',
193 - [{target: innerTag, identifier: 17}],
194 - [0],
195 - );
196 - EventEmitter.receiveTouches(
197 - 'topTouchEnd',
198 - [{target: innerTag, identifier: 17}],
199 - [0],
200 - );
201 -
202 - expect(log).toEqual([
203 - 'outer touchstart capture',
204 - 'inner touchstart capture',
205 - 'inner touchstart',
206 - 'outer touchstart',
207 - 'outer touchend capture',
208 - 'inner touchend capture',
209 - 'inner touchend',
210 - 'outer touchend',
211 - ]);
212 -});
213 -
214 -// @gate !disableLegacyContext || !__DEV__
215 -// @gate !disableLegacyMode
216 -test('handles events on text nodes', () => {
217 - expect(RCTEventEmitter.register).toHaveBeenCalledTimes(1);
218 - const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
219 - const Text = fakeRequireNativeComponent('RCTText', {});
220 -
221 - class ContextHack extends React.Component {
222 - static childContextTypes = {isInAParentText: PropTypes.bool};
223 - getChildContext() {
224 - return {isInAParentText: true};
225 - }
226 - render() {
227 - return this.props.children;
228 - }
229 - }
230 -
231 - const log = [];
232 - ReactNative.render(
233 - <ContextHack>
234 - <Text>
235 - <Text
236 - onTouchEnd={() => log.push('string touchend')}
237 - onTouchEndCapture={() => log.push('string touchend capture')}
238 - onTouchStart={() => log.push('string touchstart')}
239 - onTouchStartCapture={() => log.push('string touchstart capture')}>
240 - Text Content
241 - </Text>
242 - <Text
243 - onTouchEnd={() => log.push('number touchend')}
244 - onTouchEndCapture={() => log.push('number touchend capture')}
245 - onTouchStart={() => log.push('number touchstart')}
246 - onTouchStartCapture={() => log.push('number touchstart capture')}>
247 - {123}
248 - </Text>
249 - </Text>
250 - </ContextHack>,
251 - 1,
252 - );
253 - assertConsoleErrorDev([
254 - 'ContextHack uses the legacy childContextTypes API which will soon be removed. ' +
255 - 'Use React.createContext() instead. ' +
256 - '(https://react.dev/link/legacy-context)' +
257 - '\n in ContextHack (at **)',
258 - ]);
259 -
260 - expect(UIManager.createView).toHaveBeenCalledTimes(5);
261 -
262 - // Don't depend on the order of createView() calls.
263 - // Stack creates views outside-in; fiber creates them inside-out.
264 - const innerTagString = UIManager.createView.mock.calls.find(
265 - args => args[3] && args[3].text === 'Text Content',
266 - )[0];
267 - const innerTagNumber = UIManager.createView.mock.calls.find(
268 - args => args[3] && args[3].text === '123',
269 - )[0];
270 -
271 - EventEmitter.receiveTouches(
272 - 'topTouchStart',
273 - [{target: innerTagString, identifier: 17}],
274 - [0],
275 - );
276 - EventEmitter.receiveTouches(
277 - 'topTouchEnd',
278 - [{target: innerTagString, identifier: 17}],
279 - [0],
280 - );
281 -
282 - EventEmitter.receiveTouches(
283 - 'topTouchStart',
284 - [{target: innerTagNumber, identifier: 18}],
285 - [0],
286 - );
287 - EventEmitter.receiveTouches(
288 - 'topTouchEnd',
289 - [{target: innerTagNumber, identifier: 18}],
290 - [0],
291 - );
292 -
293 - expect(log).toEqual([
294 - 'string touchstart capture',
295 - 'string touchstart',
296 - 'string touchend capture',
297 - 'string touchend',
298 - 'number touchstart capture',
299 - 'number touchstart',
300 - 'number touchend capture',
301 - 'number touchend',
302 - ]);
303 -});
304 -
305 -// @gate !disableLegacyMode
306 -test('handles when a responder is unmounted while a touch sequence is in progress', () => {
307 - const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
308 - const View = fakeRequireNativeComponent('View', {id: true});
309 -
310 - function getViewById(id) {
311 - return UIManager.createView.mock.calls.find(
312 - args => args[3] && args[3].id === id,
313 - )[0];
314 - }
315 -
316 - function getResponderId() {
317 - const responder = ResponderEventPlugin._getResponder();
318 - if (responder === null) {
319 - return null;
320 - }
321 - const props = responder.memoizedProps;
322 - return props ? props.id : null;
323 - }
324 -
325 - const log = [];
326 - ReactNative.render(
327 - <View id="parent">
328 - <View key={1}>
329 - <View
330 - id="one"
331 - onResponderEnd={() => log.push('one responder end')}
332 - onResponderStart={() => log.push('one responder start')}
333 - onStartShouldSetResponder={() => true}
334 - />
335 - </View>
336 - <View key={2}>
337 - <View
338 - id="two"
339 - onResponderEnd={() => log.push('two responder end')}
340 - onResponderStart={() => log.push('two responder start')}
341 - onStartShouldSetResponder={() => true}
342 - />
343 - </View>
344 - </View>,
345 - 1,
346 - );
347 -
348 - EventEmitter.receiveTouches(
349 - 'topTouchStart',
350 - [{target: getViewById('one'), identifier: 17}],
351 - [0],
352 - );
353 -
354 - expect(getResponderId()).toBe('one');
355 - expect(log).toEqual(['one responder start']);
356 - log.splice(0);
357 -
358 - ReactNative.render(
359 - <View id="parent">
360 - <View key={2}>
361 - <View
362 - id="two"
363 - onResponderEnd={() => log.push('two responder end')}
364 - onResponderStart={() => log.push('two responder start')}
365 - onStartShouldSetResponder={() => true}
366 - />
367 - </View>
368 - </View>,
369 - 1,
370 - );
371 -
372 - // TODO Verify the onResponderEnd listener has been called (before the unmount)
373 - // expect(log).toEqual(['one responder end']);
374 - // log.splice(0);
375 -
376 - EventEmitter.receiveTouches(
377 - 'topTouchEnd',
378 - [{target: getViewById('two'), identifier: 17}],
379 - [0],
380 - );
381 -
382 - expect(getResponderId()).toBeNull();
383 - expect(log).toEqual([]);
384 -
385 - EventEmitter.receiveTouches(
386 - 'topTouchStart',
387 - [{target: getViewById('two'), identifier: 17}],
388 - [0],
389 - );
390 -
391 - expect(getResponderId()).toBe('two');
392 - expect(log).toEqual(['two responder start']);
393 -});
394 -
395 -// @gate !disableLegacyMode
396 -test('handles events without target', () => {
397 - const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
398 -
399 - const View = fakeRequireNativeComponent('View', {id: true});
400 -
401 - function getViewById(id) {
402 - return UIManager.createView.mock.calls.find(
403 - args => args[3] && args[3].id === id,
404 - )[0];
405 - }
406 -
407 - function getResponderId() {
408 - const responder = ResponderEventPlugin._getResponder();
409 - if (responder === null) {
410 - return null;
411 - }
412 - const props = responder.memoizedProps;
413 - return props ? props.id : null;
414 - }
415 -
416 - const log = [];
417 -
418 - function render(renderFirstComponent) {
419 - ReactNative.render(
420 - <View id="parent">
421 - <View key={1}>
422 - {renderFirstComponent ? (
423 - <View
424 - id="one"
425 - onResponderEnd={() => log.push('one responder end')}
426 - onResponderStart={() => log.push('one responder start')}
427 - onStartShouldSetResponder={() => true}
428 - />
429 - ) : null}
430 - </View>
431 - <View key={2}>
432 - <View
433 - id="two"
434 - onResponderEnd={() => log.push('two responder end')}
435 - onResponderStart={() => log.push('two responder start')}
436 - onStartShouldSetResponder={() => true}
437 - />
438 - </View>
439 - </View>,
440 - 1,
441 - );
442 - }
443 -
444 - render(true);
445 -
446 - EventEmitter.receiveTouches(
447 - 'topTouchStart',
448 - [{target: getViewById('one'), identifier: 17}],
449 - [0],
450 - );
451 -
452 - // Unmounting component 'one'.
453 - render(false);
454 -
455 - EventEmitter.receiveTouches(
456 - 'topTouchEnd',
457 - [{target: getViewById('one'), identifier: 17}],
458 - [0],
459 - );
460 -
461 - expect(getResponderId()).toBe(null);
462 -
463 - EventEmitter.receiveTouches(
464 - 'topTouchStart',
465 - [{target: getViewById('two'), identifier: 18}],
466 - [0],
467 - );
468 -
469 - expect(getResponderId()).toBe('two');
470 -
471 - EventEmitter.receiveTouches(
472 - 'topTouchEnd',
473 - [{target: getViewById('two'), identifier: 18}],
474 - [0],
475 - );
476 -
477 - expect(getResponderId()).toBe(null);
478 -
479 - expect(log).toEqual([
480 - 'one responder start',
481 - 'two responder start',
482 - 'two responder end',
483 - ]);
484 -});
485 -
486 -// @gate !disableLegacyMode
487 -test('dispatches event with target as instance', () => {
488 - const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
489 -
490 - const View = fakeRequireNativeComponent('View', {id: true});
491 -
492 - function getViewById(id) {
493 - return UIManager.createView.mock.calls.find(
494 - args => args[3] && args[3].id === id,
495 - )[0];
496 - }
497 -
498 - const ref1 = React.createRef();
499 - const ref2 = React.createRef();
500 -
501 - ReactNative.render(
502 - <View id="parent">
503 - <View
504 - ref={ref1}
505 - id="one"
506 - onResponderStart={event => {
507 - expect(ref1.current).not.toBeNull();
508 - // Check for referential equality
509 - expect(ref1.current).toBe(event.target);
510 - expect(ref1.current).toBe(event.currentTarget);
511 - }}
512 - onStartShouldSetResponder={() => true}
513 - />
514 - <View
515 - ref={ref2}
516 - id="two"
517 - onResponderStart={event => {
518 - expect(ref2.current).not.toBeNull();
519 - // Check for referential equality
520 - expect(ref2.current).toBe(event.target);
521 - expect(ref2.current).toBe(event.currentTarget);
522 - }}
523 - onStartShouldSetResponder={() => true}
524 - />
525 - </View>,
526 - 1,
527 - );
528 -
529 - EventEmitter.receiveTouches(
530 - 'topTouchStart',
531 - [{target: getViewById('one'), identifier: 17}],
532 - [0],
533 - );
534 -
535 - EventEmitter.receiveTouches(
536 - 'topTouchEnd',
537 - [{target: getViewById('one'), identifier: 17}],
538 - [0],
539 - );
540 -
541 - EventEmitter.receiveTouches(
542 - 'topTouchStart',
543 - [{target: getViewById('two'), identifier: 18}],
544 - [0],
545 - );
546 -
547 - EventEmitter.receiveTouches(
548 - 'topTouchEnd',
549 - [{target: getViewById('two'), identifier: 18}],
550 - [0],
551 - );
552 -
553 - expect.assertions(6);
554 -});
packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js deleted
-771
@@ -1,771 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @emails react-core
8 - * @jest-environment node
9 - */
10 -
11 -'use strict';
12 -
13 -let React;
14 -let StrictMode;
15 -let ReactNative;
16 -let createReactNativeComponentClass;
17 -let UIManager;
18 -let TextInputState;
19 -let ReactNativePrivateInterface;
20 -let act;
21 -let assertConsoleErrorDev;
22 -
23 -const DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT =
24 - "dispatchCommand was called with a ref that isn't a " +
25 - 'native component. Use React.forwardRef to get access to the underlying native component';
26 -
27 -const SEND_ACCESSIBILITY_EVENT_REQUIRES_HOST_COMPONENT =
28 - "sendAccessibilityEvent was called with a ref that isn't a " +
29 - 'native component. Use React.forwardRef to get access to the underlying native component';
30 -
31 -describe('ReactNative', () => {
32 - beforeEach(() => {
33 - jest.resetModules();
34 -
35 - React = require('react');
36 - ({act, assertConsoleErrorDev} = require('internal-test-utils'));
37 - StrictMode = React.StrictMode;
38 - ReactNative = require('react-native-renderer');
39 - ReactNativePrivateInterface = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface');
40 - UIManager =
41 - require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface').UIManager;
42 - createReactNativeComponentClass =
43 - require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
44 - .ReactNativeViewConfigRegistry.register;
45 - TextInputState =
46 - require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface').TextInputState;
47 - });
48 -
49 - // @gate !disableLegacyMode
50 - it('should be able to create and render a native component', () => {
51 - const View = createReactNativeComponentClass('RCTView', () => ({
52 - validAttributes: {foo: true},
53 - uiViewClassName: 'RCTView',
54 - }));
55 -
56 - ReactNative.render(<View foo="test" />, 1);
57 - expect(UIManager.createView).toBeCalled();
58 - expect(UIManager.setChildren).toBeCalled();
59 - expect(UIManager.manageChildren).not.toBeCalled();
60 - expect(UIManager.updateView).not.toBeCalled();
61 - });
62 -
63 - // @gate !disableLegacyMode
64 - it('should be able to create and update a native component', () => {
65 - const View = createReactNativeComponentClass('RCTView', () => ({
66 - validAttributes: {foo: true},
67 - uiViewClassName: 'RCTView',
68 - }));
69 -
70 - ReactNative.render(<View foo="foo" />, 11);
71 -
72 - expect(UIManager.createView).toHaveBeenCalledTimes(1);
73 - expect(UIManager.setChildren).toHaveBeenCalledTimes(1);
74 - expect(UIManager.manageChildren).not.toBeCalled();
75 - expect(UIManager.updateView).not.toBeCalled();
76 -
77 - ReactNative.render(<View foo="bar" />, 11);
78 -
79 - expect(UIManager.createView).toHaveBeenCalledTimes(1);
80 - expect(UIManager.setChildren).toHaveBeenCalledTimes(1);
81 - expect(UIManager.manageChildren).not.toBeCalled();
82 - expect(UIManager.updateView).toBeCalledWith(3, 'RCTView', {foo: 'bar'});
83 - });
84 -
85 - // @gate !disableLegacyMode
86 - it('should not call UIManager.updateView after render for properties that have not changed', () => {
87 - const Text = createReactNativeComponentClass('RCTText', () => ({
88 - validAttributes: {foo: true},
89 - uiViewClassName: 'RCTText',
90 - }));
91 -
92 - ReactNative.render(<Text foo="a">1</Text>, 11);
93 - expect(UIManager.updateView).not.toBeCalled();
94 -
95 - // If no properties have changed, we shouldn't call updateView.
96 - ReactNative.render(<Text foo="a">1</Text>, 11);
97 - expect(UIManager.updateView).not.toBeCalled();
98 -
99 - // Only call updateView for the changed property (and not for text).
100 - ReactNative.render(<Text foo="b">1</Text>, 11);
101 - expect(UIManager.updateView).toHaveBeenCalledTimes(1);
102 -
103 - // Only call updateView for the changed text (and no other properties).
104 - ReactNative.render(<Text foo="b">2</Text>, 11);
105 - expect(UIManager.updateView).toHaveBeenCalledTimes(2);
106 -
107 - // Call updateView for both changed text and properties.
108 - ReactNative.render(<Text foo="c">3</Text>, 11);
109 - expect(UIManager.updateView).toHaveBeenCalledTimes(4);
110 - });
111 -
112 - // @gate !disableLegacyMode
113 - it('should call dispatchCommand for native refs', () => {
114 - const View = createReactNativeComponentClass('RCTView', () => ({
115 - validAttributes: {foo: true},
116 - uiViewClassName: 'RCTView',
117 - }));
118 -
119 - UIManager.dispatchViewManagerCommand.mockClear();
120 -
121 - let viewRef;
122 - ReactNative.render(
123 - <View
124 - ref={ref => {
125 - viewRef = ref;
126 - }}
127 - />,
128 - 11,
129 - );
130 -
131 - expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
132 - ReactNative.dispatchCommand(viewRef, 'updateCommand', [10, 20]);
133 - expect(UIManager.dispatchViewManagerCommand).toHaveBeenCalledTimes(1);
134 - expect(UIManager.dispatchViewManagerCommand).toHaveBeenCalledWith(
135 - expect.any(Number),
136 - 'updateCommand',
137 - [10, 20],
138 - );
139 - });
140 -
141 - // @gate !disableLegacyMode
142 - it('should warn and no-op if calling dispatchCommand on non native refs', () => {
143 - class BasicClass extends React.Component {
144 - render() {
145 - return <React.Fragment />;
146 - }
147 - }
148 -
149 - UIManager.dispatchViewManagerCommand.mockReset();
150 -
151 - let viewRef;
152 - ReactNative.render(
153 - <BasicClass
154 - ref={ref => {
155 - viewRef = ref;
156 - }}
157 - />,
158 - 11,
159 - );
160 -
161 - expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
162 - ReactNative.dispatchCommand(viewRef, 'updateCommand', [10, 20]);
163 - assertConsoleErrorDev([DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT], {
164 - withoutStack: true,
165 - });
166 -
167 - expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
168 - });
169 -
170 - // @gate !disableLegacyMode
171 - it('should call sendAccessibilityEvent for native refs', () => {
172 - const View = createReactNativeComponentClass('RCTView', () => ({
173 - validAttributes: {foo: true},
174 - uiViewClassName: 'RCTView',
175 - }));
176 -
177 - ReactNativePrivateInterface.legacySendAccessibilityEvent.mockClear();
178 -
179 - let viewRef;
180 - ReactNative.render(
181 - <View
182 - ref={ref => {
183 - viewRef = ref;
184 - }}
185 - />,
186 - 11,
187 - );
188 -
189 - expect(
190 - ReactNativePrivateInterface.legacySendAccessibilityEvent,
191 - ).not.toBeCalled();
192 - ReactNative.sendAccessibilityEvent(viewRef, 'focus');
193 - expect(
194 - ReactNativePrivateInterface.legacySendAccessibilityEvent,
195 - ).toHaveBeenCalledTimes(1);
196 - expect(
197 - ReactNativePrivateInterface.legacySendAccessibilityEvent,
198 - ).toHaveBeenCalledWith(expect.any(Number), 'focus');
199 - });
200 -
201 - // @gate !disableLegacyMode
202 - it('should warn and no-op if calling sendAccessibilityEvent on non native refs', () => {
203 - class BasicClass extends React.Component {
204 - render() {
205 - return <React.Fragment />;
206 - }
207 - }
208 -
209 - UIManager.sendAccessibilityEvent.mockReset();
210 -
211 - let viewRef;
212 - ReactNative.render(
213 - <BasicClass
214 - ref={ref => {
215 - viewRef = ref;
216 - }}
217 - />,
218 - 11,
219 - );
220 -
221 - expect(UIManager.sendAccessibilityEvent).not.toBeCalled();
222 - ReactNative.sendAccessibilityEvent(viewRef, 'updateCommand', [10, 20]);
223 - assertConsoleErrorDev([SEND_ACCESSIBILITY_EVENT_REQUIRES_HOST_COMPONENT], {
224 - withoutStack: true,
225 - });
226 -
227 - expect(UIManager.sendAccessibilityEvent).not.toBeCalled();
228 - });
229 -
230 - // @gate !disableLegacyMode
231 - it('should not call UIManager.updateView from ref.setNativeProps for properties that have not changed', () => {
232 - const View = createReactNativeComponentClass('RCTView', () => ({
233 - validAttributes: {foo: true},
234 - uiViewClassName: 'RCTView',
235 - }));
236 -
237 - UIManager.updateView.mockReset();
238 -
239 - let viewRef;
240 - ReactNative.render(
241 - <View
242 - foo="bar"
243 - ref={ref => {
244 - viewRef = ref;
245 - }}
246 - />,
247 - 11,
248 - );
249 -
250 - expect(UIManager.updateView).not.toBeCalled();
251 -
252 - viewRef.setNativeProps({});
253 - expect(UIManager.updateView).not.toBeCalled();
254 -
255 - viewRef.setNativeProps({foo: 'baz'});
256 - expect(UIManager.updateView).toHaveBeenCalledTimes(1);
257 - expect(UIManager.updateView).toHaveBeenCalledWith(
258 - expect.any(Number),
259 - 'RCTView',
260 - {foo: 'baz'},
261 - );
262 - });
263 -
264 - // @gate !disableLegacyMode
265 - it('should call UIManager.measure on ref.measure', () => {
266 - const View = createReactNativeComponentClass('RCTView', () => ({
267 - validAttributes: {foo: true},
268 - uiViewClassName: 'RCTView',
269 - }));
270 -
271 - UIManager.measure.mockClear();
272 -
273 - let viewRef;
274 - ReactNative.render(
275 - <View
276 - ref={ref => {
277 - viewRef = ref;
278 - }}
279 - />,
280 - 11,
281 - );
282 -
283 - expect(UIManager.measure).not.toBeCalled();
284 - const successCallback = jest.fn();
285 - viewRef.measure(successCallback);
286 - expect(UIManager.measure).toHaveBeenCalledTimes(1);
287 - expect(successCallback).toHaveBeenCalledTimes(1);
288 - expect(successCallback).toHaveBeenCalledWith(10, 10, 100, 100, 0, 0);
289 - });
290 -
291 - // @gate !disableLegacyMode
292 - it('should call UIManager.measureInWindow on ref.measureInWindow', () => {
293 - const View = createReactNativeComponentClass('RCTView', () => ({
294 - validAttributes: {foo: true},
295 - uiViewClassName: 'RCTView',
296 - }));
297 -
298 - UIManager.measureInWindow.mockClear();
299 -
300 - let viewRef;
301 - ReactNative.render(
302 - <View
303 - ref={ref => {
304 - viewRef = ref;
305 - }}
306 - />,
307 - 11,
308 - );
309 -
310 - expect(UIManager.measureInWindow).not.toBeCalled();
311 - const successCallback = jest.fn();
312 - viewRef.measureInWindow(successCallback);
313 - expect(UIManager.measureInWindow).toHaveBeenCalledTimes(1);
314 - expect(successCallback).toHaveBeenCalledTimes(1);
315 - expect(successCallback).toHaveBeenCalledWith(10, 10, 100, 100);
316 - });
317 -
318 - // @gate !disableLegacyMode
319 - it('should support reactTag in ref.measureLayout', () => {
320 - const View = createReactNativeComponentClass('RCTView', () => ({
321 - validAttributes: {foo: true},
322 - uiViewClassName: 'RCTView',
323 - }));
324 -
325 - UIManager.measureLayout.mockClear();
326 -
327 - let viewRef;
328 - let otherRef;
329 - ReactNative.render(
330 - <View>
331 - <View
332 - foo="bar"
333 - ref={ref => {
334 - viewRef = ref;
335 - }}
336 - />
337 - <View
338 - ref={ref => {
339 - otherRef = ref;
340 - }}
341 - />
342 - </View>,
343 - 11,
344 - );
345 -
346 - expect(UIManager.measureLayout).not.toBeCalled();
347 - const successCallback = jest.fn();
348 - const failureCallback = jest.fn();
349 - viewRef.measureLayout(
350 - ReactNative.findNodeHandle(otherRef),
351 - successCallback,
352 - failureCallback,
353 - );
354 - expect(UIManager.measureLayout).toHaveBeenCalledTimes(1);
355 - expect(successCallback).toHaveBeenCalledTimes(1);
356 - expect(successCallback).toHaveBeenCalledWith(1, 1, 100, 100);
357 - });
358 -
359 - // @gate !disableLegacyMode
360 - it('should support ref in ref.measureLayout of host components', () => {
361 - const View = createReactNativeComponentClass('RCTView', () => ({
362 - validAttributes: {foo: true},
363 - uiViewClassName: 'RCTView',
364 - }));
365 -
366 - UIManager.measureLayout.mockClear();
367 -
368 - let viewRef;
369 - let otherRef;
370 - ReactNative.render(
371 - <View>
372 - <View
373 - foo="bar"
374 - ref={ref => {
375 - viewRef = ref;
376 - }}
377 - />
378 - <View
379 - ref={ref => {
380 - otherRef = ref;
381 - }}
382 - />
383 - </View>,
384 - 11,
385 - );
386 -
387 - expect(UIManager.measureLayout).not.toBeCalled();
388 - const successCallback = jest.fn();
389 - const failureCallback = jest.fn();
390 - viewRef.measureLayout(otherRef, successCallback, failureCallback);
391 - expect(UIManager.measureLayout).toHaveBeenCalledTimes(1);
392 - expect(successCallback).toHaveBeenCalledTimes(1);
393 - expect(successCallback).toHaveBeenCalledWith(1, 1, 100, 100);
394 - });
395 -
396 - // @gate !disableLegacyMode
397 - it('returns the correct instance and calls it in the callback', () => {
398 - const View = createReactNativeComponentClass('RCTView', () => ({
399 - validAttributes: {foo: true},
400 - uiViewClassName: 'RCTView',
401 - }));
402 -
403 - let a;
404 - let b;
405 - const c = ReactNative.render(
406 - <View foo="foo" ref={v => (a = v)} />,
407 - 11,
408 - function () {
409 - b = this;
410 - },
411 - );
412 -
413 - expect(a).toBeTruthy();
414 - expect(a).toBe(b);
415 - expect(a).toBe(c);
416 - });
417 -
418 - // @gate !disableLegacyMode
419 - it('renders and reorders children', () => {
420 - const View = createReactNativeComponentClass('RCTView', () => ({
421 - validAttributes: {title: true},
422 - uiViewClassName: 'RCTView',
423 - }));
424 -
425 - class Component extends React.Component {
426 - render() {
427 - const chars = this.props.chars.split('');
428 - return (
429 - <View>
430 - {chars.map(text => (
431 - <View key={text} title={text} />
432 - ))}
433 - </View>
434 - );
435 - }
436 - }
437 -
438 - // Mini multi-child stress test: lots of reorders, some adds, some removes.
439 - const before = 'abcdefghijklmnopqrst';
440 - const after = 'mxhpgwfralkeoivcstzy';
441 -
442 - ReactNative.render(<Component chars={before} />, 11);
443 - expect(UIManager.__dumpHierarchyForJestTestsOnly()).toMatchInlineSnapshot(`
444 - "<native root> {}
445 - RCTView null
446 - RCTView {"title":"a"}
447 - RCTView {"title":"b"}
448 - RCTView {"title":"c"}
449 - RCTView {"title":"d"}
450 - RCTView {"title":"e"}
451 - RCTView {"title":"f"}
452 - RCTView {"title":"g"}
453 - RCTView {"title":"h"}
454 - RCTView {"title":"i"}
455 - RCTView {"title":"j"}
456 - RCTView {"title":"k"}
457 - RCTView {"title":"l"}
458 - RCTView {"title":"m"}
459 - RCTView {"title":"n"}
460 - RCTView {"title":"o"}
461 - RCTView {"title":"p"}
462 - RCTView {"title":"q"}
463 - RCTView {"title":"r"}
464 - RCTView {"title":"s"}
465 - RCTView {"title":"t"}"
466 - `);
467 -
468 - ReactNative.render(<Component chars={after} />, 11);
469 - expect(UIManager.__dumpHierarchyForJestTestsOnly()).toMatchInlineSnapshot(`
470 - "<native root> {}
471 - RCTView null
472 - RCTView {"title":"m"}
473 - RCTView {"title":"x"}
474 - RCTView {"title":"h"}
475 - RCTView {"title":"p"}
476 - RCTView {"title":"g"}
477 - RCTView {"title":"w"}
478 - RCTView {"title":"f"}
479 - RCTView {"title":"r"}
480 - RCTView {"title":"a"}
481 - RCTView {"title":"l"}
482 - RCTView {"title":"k"}
483 - RCTView {"title":"e"}
484 - RCTView {"title":"o"}
485 - RCTView {"title":"i"}
486 - RCTView {"title":"v"}
487 - RCTView {"title":"c"}
488 - RCTView {"title":"s"}
489 - RCTView {"title":"t"}
490 - RCTView {"title":"z"}
491 - RCTView {"title":"y"}"
492 - `);
493 - });
494 -
495 - // @gate !disableLegacyMode
496 - it('calls setState with no arguments', () => {
497 - let mockArgs;
498 - class Component extends React.Component {
499 - componentDidMount() {
500 - this.setState({}, (...args) => (mockArgs = args));
501 - }
502 - render() {
503 - return false;
504 - }
505 - }
506 -
507 - ReactNative.render(<Component />, 11);
508 - expect(mockArgs.length).toEqual(0);
509 - });
510 -
511 - // @gate !disableLegacyMode
512 - it('should not throw when <View> is used inside of a <Text> ancestor', () => {
513 - const Image = createReactNativeComponentClass('RCTImage', () => ({
514 - validAttributes: {},
515 - uiViewClassName: 'RCTImage',
516 - }));
517 - const Text = createReactNativeComponentClass('RCTText', () => ({
518 - validAttributes: {},
519 - uiViewClassName: 'RCTText',
520 - }));
521 - const View = createReactNativeComponentClass('RCTView', () => ({
522 - validAttributes: {},
523 - uiViewClassName: 'RCTView',
524 - }));
525 -
526 - ReactNative.render(
527 - <Text>
528 - <View />
529 - </Text>,
530 - 11,
531 - );
532 -
533 - // Non-View things (e.g. Image) are fine
534 - ReactNative.render(
535 - <Text>
536 - <Image />
537 - </Text>,
538 - 11,
539 - );
540 - });
541 -
542 - // @gate !disableLegacyMode
543 - it('should throw for text not inside of a <Text> ancestor', async () => {
544 - const ScrollView = createReactNativeComponentClass('RCTScrollView', () => ({
545 - validAttributes: {},
546 - uiViewClassName: 'RCTScrollView',
547 - }));
548 - const Text = createReactNativeComponentClass('RCTText', () => ({
549 - validAttributes: {},
550 - uiViewClassName: 'RCTText',
551 - }));
552 - const View = createReactNativeComponentClass('RCTView', () => ({
553 - validAttributes: {},
554 - uiViewClassName: 'RCTView',
555 - }));
556 -
557 - await expect(async () => {
558 - await act(() => ReactNative.render(<View>this should warn</View>, 11));
559 - }).rejects.toThrow(
560 - 'Text strings must be rendered within a <Text> component.',
561 - );
562 -
563 - await expect(async () => {
564 - await act(() =>
565 - ReactNative.render(
566 - <Text>
567 - <ScrollView>hi hello hi</ScrollView>
568 - </Text>,
569 - 11,
570 - ),
571 - );
572 - }).rejects.toThrow(
573 - 'Text strings must be rendered within a <Text> component.',
574 - );
575 - });
576 -
577 - // @gate !disableLegacyMode
578 - it('should not throw for text inside of an indirect <Text> ancestor', () => {
579 - const Text = createReactNativeComponentClass('RCTText', () => ({
580 - validAttributes: {},
581 - uiViewClassName: 'RCTText',
582 - }));
583 -
584 - const Indirection = () => 'Hi';
585 -
586 - ReactNative.render(
587 - <Text>
588 - <Indirection />
589 - </Text>,
590 - 11,
591 - );
592 - });
593 -
594 - // @gate !disableLegacyMode
595 - it('findHostInstance_DEPRECATED should warn if used to find a host component inside StrictMode', () => {
596 - const View = createReactNativeComponentClass('RCTView', () => ({
597 - validAttributes: {foo: true},
598 - uiViewClassName: 'RCTView',
599 - }));
600 -
601 - let parent = undefined;
602 - let child = undefined;
603 -
604 - class ContainsStrictModeChild extends React.Component {
605 - render() {
606 - return (
607 - <StrictMode>
608 - <View ref={n => (child = n)} />
609 - </StrictMode>
610 - );
611 - }
612 - }
613 -
614 - ReactNative.render(<ContainsStrictModeChild ref={n => (parent = n)} />, 11);
615 -
616 - const match = ReactNative.findHostInstance_DEPRECATED(parent);
617 - assertConsoleErrorDev([
618 - 'findHostInstance_DEPRECATED is deprecated in StrictMode. ' +
619 - 'findHostInstance_DEPRECATED was passed an instance of ContainsStrictModeChild which renders StrictMode children. ' +
620 - 'Instead, add a ref directly to the element you want to reference. ' +
621 - 'Learn more about using refs safely here: ' +
622 - 'https://react.dev/link/strict-mode-find-node' +
623 - '\n in RCTView (at **)' +
624 - '\n in ContainsStrictModeChild (at **)',
625 - ]);
626 - expect(match).toBe(child);
627 - });
628 -
629 - // @gate !disableLegacyMode
630 - it('findHostInstance_DEPRECATED should warn if passed a component that is inside StrictMode', () => {
631 - const View = createReactNativeComponentClass('RCTView', () => ({
632 - validAttributes: {foo: true},
633 - uiViewClassName: 'RCTView',
634 - }));
635 -
636 - let parent = undefined;
637 - let child = undefined;
638 -
639 - class IsInStrictMode extends React.Component {
640 - render() {
641 - return <View ref={n => (child = n)} />;
642 - }
643 - }
644 -
645 - ReactNative.render(
646 - <StrictMode>
647 - <IsInStrictMode ref={n => (parent = n)} />
648 - </StrictMode>,
649 - 11,
650 - );
651 -
652 - const match = ReactNative.findHostInstance_DEPRECATED(parent);
653 - assertConsoleErrorDev([
654 - 'findHostInstance_DEPRECATED is deprecated in StrictMode. ' +
655 - 'findHostInstance_DEPRECATED was passed an instance of IsInStrictMode which is inside StrictMode. ' +
656 - 'Instead, add a ref directly to the element you want to reference. ' +
657 - 'Learn more about using refs safely here: ' +
658 - 'https://react.dev/link/strict-mode-find-node' +
659 - '\n in RCTView (at **)' +
660 - '\n in IsInStrictMode (at **)',
661 - ]);
662 - expect(match).toBe(child);
663 - });
664 -
665 - // @gate !disableLegacyMode
666 - it('findNodeHandle should warn if used to find a host component inside StrictMode', () => {
667 - const View = createReactNativeComponentClass('RCTView', () => ({
668 - validAttributes: {foo: true},
669 - uiViewClassName: 'RCTView',
670 - }));
671 -
672 - let parent = undefined;
673 - let child = undefined;
674 -
675 - class ContainsStrictModeChild extends React.Component {
676 - render() {
677 - return (
678 - <StrictMode>
679 - <View ref={n => (child = n)} />
680 - </StrictMode>
681 - );
682 - }
683 - }
684 -
685 - ReactNative.render(<ContainsStrictModeChild ref={n => (parent = n)} />, 11);
686 -
687 - const match = ReactNative.findNodeHandle(parent);
688 - assertConsoleErrorDev([
689 - 'findNodeHandle is deprecated in StrictMode. ' +
690 - 'findNodeHandle was passed an instance of ContainsStrictModeChild which renders StrictMode children. ' +
691 - 'Instead, add a ref directly to the element you want to reference. ' +
692 - 'Learn more about using refs safely here: ' +
693 - 'https://react.dev/link/strict-mode-find-node' +
694 - '\n in RCTView (at **)' +
695 - '\n in ContainsStrictModeChild (at **)',
696 - ]);
697 - expect(match).toBe(child._nativeTag);
698 - });
699 -
700 - // @gate !disableLegacyMode
701 - it('findNodeHandle should warn if passed a component that is inside StrictMode', () => {
702 - const View = createReactNativeComponentClass('RCTView', () => ({
703 - validAttributes: {foo: true},
704 - uiViewClassName: 'RCTView',
705 - }));
706 -
707 - let parent = undefined;
708 - let child = undefined;
709 -
710 - class IsInStrictMode extends React.Component {
711 - render() {
712 - return <View ref={n => (child = n)} />;
713 - }
714 - }
715 -
716 - ReactNative.render(
717 - <StrictMode>
718 - <IsInStrictMode ref={n => (parent = n)} />
719 - </StrictMode>,
720 - 11,
721 - );
722 -
723 - const match = ReactNative.findNodeHandle(parent);
724 - assertConsoleErrorDev([
725 - 'findNodeHandle is deprecated in StrictMode. ' +
726 - 'findNodeHandle was passed an instance of IsInStrictMode which is inside StrictMode. ' +
727 - 'Instead, add a ref directly to the element you want to reference. ' +
728 - 'Learn more about using refs safely here: ' +
729 - 'https://react.dev/link/strict-mode-find-node' +
730 - '\n in RCTView (at **)' +
731 - '\n in IsInStrictMode (at **)',
732 - ]);
733 - expect(match).toBe(child._nativeTag);
734 - });
735 -
736 - // @gate !disableLegacyMode
737 - it('blur on host component calls TextInputState', () => {
738 - const View = createReactNativeComponentClass('RCTView', () => ({
739 - validAttributes: {foo: true},
740 - uiViewClassName: 'RCTView',
741 - }));
742 -
743 - const viewRef = React.createRef();
744 - ReactNative.render(<View ref={viewRef} />, 11);
745 -
746 - expect(TextInputState.blurTextInput).not.toBeCalled();
747 -
748 - viewRef.current.blur();
749 -
750 - expect(TextInputState.blurTextInput).toHaveBeenCalledTimes(1);
751 - expect(TextInputState.blurTextInput).toHaveBeenCalledWith(viewRef.current);
752 - });
753 -
754 - // @gate !disableLegacyMode
755 - it('focus on host component calls TextInputState', () => {
756 - const View = createReactNativeComponentClass('RCTView', () => ({
757 - validAttributes: {foo: true},
758 - uiViewClassName: 'RCTView',
759 - }));
760 -
761 - const viewRef = React.createRef();
762 - ReactNative.render(<View ref={viewRef} />, 11);
763 -
764 - expect(TextInputState.focusTextInput).not.toBeCalled();
765 -
766 - viewRef.current.focus();
767 -
768 - expect(TextInputState.focusTextInput).toHaveBeenCalledTimes(1);
769 - expect(TextInputState.focusTextInput).toHaveBeenCalledWith(viewRef.current);
770 - });
771 -});
packages/react-native-renderer/src/__tests__/createReactNativeComponentClass-test.internal.js deleted
-76
@@ -1,76 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @emails react-core
8 - * @jest-environment node
9 - */
10 -
11 -'use strict';
12 -
13 -let createReactNativeComponentClass;
14 -let React;
15 -let ReactNative;
16 -
17 -describe('createReactNativeComponentClass', () => {
18 - beforeEach(() => {
19 - jest.resetModules();
20 -
21 - createReactNativeComponentClass =
22 - require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
23 - .ReactNativeViewConfigRegistry.register;
24 - React = require('react');
25 - ReactNative = require('react-native-renderer');
26 - });
27 -
28 - // @gate !disableLegacyMode
29 - it('should register viewConfigs', () => {
30 - const textViewConfig = {
31 - validAttributes: {},
32 - uiViewClassName: 'Text',
33 - };
34 - const viewViewConfig = {
35 - validAttributes: {},
36 - uiViewClassName: 'View',
37 - };
38 -
39 - const Text = createReactNativeComponentClass(
40 - textViewConfig.uiViewClassName,
41 - () => textViewConfig,
42 - );
43 - const View = createReactNativeComponentClass(
44 - viewViewConfig.uiViewClassName,
45 - () => viewViewConfig,
46 - );
47 -
48 - expect(Text).not.toBe(View);
49 -
50 - ReactNative.render(<Text />, 1);
51 - ReactNative.render(<View />, 1);
52 - });
53 -
54 - it('should not allow viewConfigs with duplicate uiViewClassNames to be registered', () => {
55 - const textViewConfig = {
56 - validAttributes: {},
57 - uiViewClassName: 'Text',
58 - };
59 - const altTextViewConfig = {
60 - validAttributes: {},
61 - uiViewClassName: 'Text', // Same
62 - };
63 -
64 - createReactNativeComponentClass(
65 - textViewConfig.uiViewClassName,
66 - () => textViewConfig,
67 - );
68 -
69 - expect(() => {
70 - createReactNativeComponentClass(
71 - altTextViewConfig.uiViewClassName,
72 - () => altTextViewConfig,
73 - );
74 - }).toThrow('Tried to register two views with the same name Text');
75 - });
76 -});
packages/react-reconciler/src/forks/ReactFiberConfig.native.js deleted
-11
@@ -1,11 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -export * from 'react-native-renderer/src/ReactFiberConfigNative';
11 -export * from 'react-client/src/ReactClientConsoleConfigPlain';
packages/react/src/__tests__/ReactMismatchedVersions-test.js
-10
@@ -136,14 +136,4 @@ describe('ReactMismatchedVersions-test', () => {
136 ` - react-dom: ${actualReactVersion}`,
137 );
138 });
139 -
140 - // @gate source
141 - it('importing "react-native-renderer" throws if version does not match React version', async () => {
142 - expect(() => require('react-native-renderer')).toThrow(
143 - 'Incompatible React versions: The "react" and "react-native-renderer" packages ' +
144 - 'must have the exact same version. Instead got:\n' +
145 - ' - react: 18.0.0-whoa-this-aint-the-right-react\n' +
146 - ` - react-native-renderer: ${actualReactVersion}`,
147 - );
148 - });
139 });
scripts/flow/react-native-host-hooks.js
-103
@@ -42,7 +42,6 @@ type __RNTopLevelEventType = any;
42 // from 'react-reconciler/src/ReactCapturedValue'
43 type __CapturedError = any;
44
45 -type DeepDifferOptions = {+unsafelyIgnoreFunctions?: boolean};
45 type RawEventEmitterEvent = $ReadOnly<{
46 eventName: string,
47 // We expect, but do not/cannot require, that nativeEvent is an object
@@ -56,101 +55,11 @@ declare opaque type __PublicTextInstance;
55 declare opaque type __PublicRootInstance;
56
57 declare module 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface' {
59 - declare export function deepDiffer(
60 - one: any,
61 - two: any,
62 - maxDepth?: number,
63 - options?: DeepDifferOptions,
64 - ): boolean;
65 - declare export function deepDiffer(
66 - one: any,
67 - two: any,
68 - options: DeepDifferOptions,
69 - ): boolean;
58 declare export function deepFreezeAndThrowOnMutationInDev<T>(obj: T): T;
71 - declare export function flattenStyle(style: any): any;
72 - declare export const RCTEventEmitter: {
73 - register: (eventEmitter: mixed) => void,
74 - ...
75 - };
76 - declare export const TextInputState: {
77 - blurTextInput: (object: any) => void,
78 - focusTextInput: (object: any) => void,
79 - ...
80 - };
59 declare export const ReactFiberErrorDialog: {
60 showErrorDialog: (error: __CapturedError) => boolean,
61 ...
62 };
85 - declare export const Platform: {OS: string, ...};
86 - declare export const UIManager: {
87 - customBubblingEventTypes: Object,
88 - customDirectEventTypes: Object,
89 - createView: (
90 - reactTag: number,
91 - viewName: string,
92 - rootTag: number,
93 - props: ?Object,
94 - ) => void,
95 - dispatchViewManagerCommand: (
96 - reactTag: number,
97 - command: string,
98 - args: Array<any>,
99 - ) => void,
100 - manageChildren: (
101 - containerTag: number,
102 - moveFromIndices: Array<number>,
103 - moveToIndices: Array<number>,
104 - addChildReactTags: Array<number>,
105 - addAtIndices: Array<number>,
106 - removeAtIndices: Array<number>,
107 - ) => void,
108 - measure: (hostComponent: mixed, callback: Function) => void,
109 - measureInWindow: (nativeTag: ?number, callback: Function) => void,
110 - measureLayout: (
111 - nativeTag: mixed,
112 - nativeNode: number,
113 - onFail: Function,
114 - onSuccess: Function,
115 - ) => void,
116 - removeRootView: (containerTag: number) => void,
117 - removeSubviewsFromContainerWithID: (containerId: number) => void,
118 - replaceExistingNonRootView: () => void,
119 - setChildren: (containerTag: number, reactTags: Array<number>) => void,
120 - updateView: (reactTag: number, viewName: string, props: ?Object) => void,
121 - __takeSnapshot: (
122 - view?: 'window' | Element | number,
123 - options?: {
124 - width?: number,
125 - height?: number,
126 - format?: 'png' | 'jpeg',
127 - quality?: number,
128 - ...
129 - },
130 - ) => Promise<any>,
131 - setJSResponder: (reactTag: number, blockNativeResponder: boolean) => void,
132 - clearJSResponder: () => void,
133 - findSubviewIn: (
134 - reactTag: ?number,
135 - point: Array<number>,
136 - callback: (
137 - nativeViewTag: number,
138 - left: number,
139 - top: number,
140 - width: number,
141 - height: number,
142 - ) => void,
143 - ) => void,
144 - ...
145 - };
146 - declare export const legacySendAccessibilityEvent: (
147 - reactTag: number,
148 - eventTypeName: string,
149 - ) => void;
150 - declare export const BatchedBridge: {
151 - registerCallableModule: (name: string, module: Object) => void,
152 - ...
153 - };
63 declare export const ReactNativeViewConfigRegistry: {
64 customBubblingEventTypes: Object,
65 customDirectEventTypes: Object,
@@ -171,18 +80,6 @@ declare module 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface'
80 __MeasureInWindowOnSuccessCallback;
81 declare export type MeasureLayoutOnSuccessCallback =
82 __MeasureLayoutOnSuccessCallback;
174 - declare export interface LegacyPublicInstance {
175 - blur(): void;
176 - focus(): void;
177 - measure(callback: __MeasureOnSuccessCallback): void;
178 - measureInWindow(callback: __MeasureInWindowOnSuccessCallback): void;
179 - measureLayout(
180 - relativeToNativeNode: number | LegacyPublicInstance,
181 - onSuccess: __MeasureLayoutOnSuccessCallback,
182 - onFail?: () => void,
183 - ): void;
184 - setNativeProps(nativeProps: {...}): void;
185 - }
83 declare export function getNodeFromPublicInstance(
84 publicInstance: PublicInstance,
85 ): Object;
scripts/rollup/forks.js
-15
@@ -133,21 +133,6 @@ const forks = Object.freeze({
133 // We have a few forks for different environments.
134 './packages/shared/ReactFeatureFlags.js': (bundleType, entry) => {
135 switch (entry) {
136 - case 'react-native-renderer':
137 - switch (bundleType) {
138 - case RN_FB_DEV:
139 - case RN_FB_PROD:
140 - case RN_FB_PROFILING:
141 - return './packages/shared/forks/ReactFeatureFlags.native-fb.js';
142 - case RN_OSS_DEV:
143 - case RN_OSS_PROD:
144 - case RN_OSS_PROFILING:
145 - return './packages/shared/forks/ReactFeatureFlags.native-oss.js';
146 - default:
147 - throw Error(
148 - `Unexpected entry (${entry}) and bundleType (${bundleType})`
149 - );
150 - }
136 case 'react-native-renderer/fabric':
137 switch (bundleType) {
138 case RN_FB_DEV:
scripts/rollup/shims/react-native/ReactNative.js deleted
-24
@@ -1,24 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @noformat
8 - * @nolint
9 - * @flow
10 - */
11 -'use strict';
12 -
13 -import type {ReactNativeType} from './ReactNativeTypes';
14 -
15 -let ReactNative: ReactNativeType;
16 -
17 -// TODO: Delete the legacy renderer. Only ReactFabric is used now.
18 -if (__DEV__) {
19 - ReactNative = require('../implementations/ReactNativeRenderer-dev');
20 -} else {
21 - ReactNative = require('../implementations/ReactNativeRenderer-prod');
22 -}
23 -
24 -export default ReactNative;
scripts/shared/inlinedHostConfigs.js
-10
@@ -621,16 +621,6 @@ module.exports = [
621 isServerSupported: true,
622 isFlightSupported: false,
623 },
624 - {
625 - shortName: 'native',
626 - entryPoints: ['react-native-renderer'],
627 - paths: [
628 - 'react-native-renderer',
629 - 'react-server/src/ReactFlightServerConfigDebugNoop.js',
630 - ],
631 - isFlowTyped: true,
632 - isServerSupported: false,
633 - },
624 {
625 shortName: 'fabric',
626 entryPoints: ['react-native-renderer/fabric'],