Skip to content

Commit 1e94e01

Browse files
committed
Extracted definition and access to public instances to a separate module in Fabric
1 parent d825d6e commit 1e94e01

10 files changed

+328
-191
lines changed

packages/react-native-renderer/src/ReactFabricComponentTree.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ import {getPublicInstance} from './ReactFabricHostConfig';
2020
// This is ok in DOM because they types are interchangeable, but in React Native
2121
// they aren't.
2222
function getInstanceFromNode(node: Instance | TextInstance): Fiber | null {
23+
const instance: Instance = (node: $FlowFixMe); // In React Native, node is never a text instance
24+
25+
if (
26+
instance.internals != null &&
27+
instance.internals.internalInstanceHandle != null
28+
) {
29+
return instance.internals.internalInstanceHandle;
30+
}
31+
2332
// $FlowFixMe[incompatible-return] DevTools incorrectly passes a fiber in React Native.
2433
return node;
2534
}
@@ -35,7 +44,7 @@ function getNodeFromInstance(fiber: Fiber): PublicInstance {
3544
}
3645

3746
function getFiberCurrentPropsFromNode(instance: Instance): Props {
38-
return instance.canonical.currentProps;
47+
return instance && instance.internals && instance.internals.currentProps;
3948
}
4049

4150
export {

packages/react-native-renderer/src/ReactFabricHostConfig.js

Lines changed: 37 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,13 @@
77
* @flow
88
*/
99

10-
import type {ElementRef} from 'react';
11-
import type {
12-
HostComponent,
13-
MeasureInWindowOnSuccessCallback,
14-
MeasureLayoutOnSuccessCallback,
15-
MeasureOnSuccessCallback,
16-
NativeMethods,
17-
ViewConfig,
18-
TouchedViewDataAtPoint,
19-
} from './ReactNativeTypes';
20-
21-
import {warnForStyleProps} from './NativeMethodsMixinUtils';
10+
import type {TouchedViewDataAtPoint, ViewConfig} from './ReactNativeTypes';
11+
import {
12+
createPublicInstance,
13+
type ReactFabricHostComponent,
14+
} from './ReactFabricPublicInstance';
2215
import {create, diff} from './ReactNativeAttributePayload';
23-
2416
import {dispatchEvent} from './ReactFabricEventEmitter';
25-
2617
import {
2718
DefaultEventPriority,
2819
DiscreteEventPriority,
@@ -31,7 +22,6 @@ import {
3122
// Modules provided by RN:
3223
import {
3324
ReactNativeViewConfigRegistry,
34-
TextInputState,
3525
deepFreezeAndThrowOnMutationInDev,
3626
} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
3727

@@ -46,14 +36,9 @@ const {
4636
appendChildToSet: appendChildNodeToSet,
4737
completeRoot,
4838
registerEventHandler,
49-
measure: fabricMeasure,
50-
measureInWindow: fabricMeasureInWindow,
51-
measureLayout: fabricMeasureLayout,
5239
unstable_DefaultEventPriority: FabricDefaultPriority,
5340
unstable_DiscreteEventPriority: FabricDiscretePriority,
5441
unstable_getCurrentEventPriority: fabricGetCurrentEventPriority,
55-
setNativeProps,
56-
getBoundingClientRect: fabricGetBoundingClientRect,
5742
} = nativeFabricUIManager;
5843

5944
const {get: getViewConfigForType} = ReactNativeViewConfigRegistry;
@@ -68,9 +53,18 @@ type Node = Object;
6853
export type Type = string;
6954
export type Props = Object;
7055
export type Instance = {
56+
// Reference to the shadow node.
7157
node: Node,
72-
canonical: ReactFabricHostComponent,
73-
...
58+
// Exposed through refs.
59+
publicInstance: ReactFabricHostComponent,
60+
// We define this as an object instead of as separate fields to simplify
61+
// making copies of instance where `internals` don't change.
62+
internals: {
63+
nativeTag: number,
64+
viewConfig: ViewConfig,
65+
currentProps: Props,
66+
internalInstanceHandle: Object,
67+
},
7468
};
7569
export type TextInstance = {node: Node, ...};
7670
export type HydratableInstance = Instance | TextInstance;
@@ -104,131 +98,6 @@ if (registerEventHandler) {
10498
registerEventHandler(dispatchEvent);
10599
}
106100

107-
const noop = () => {};
108-
109-
/**
110-
* This is used for refs on host components.
111-
*/
112-
class ReactFabricHostComponent implements NativeMethods {
113-
_nativeTag: number;
114-
viewConfig: ViewConfig;
115-
currentProps: Props;
116-
_internalInstanceHandle: Object;
117-
118-
constructor(
119-
tag: number,
120-
viewConfig: ViewConfig,
121-
props: Props,
122-
internalInstanceHandle: Object,
123-
) {
124-
this._nativeTag = tag;
125-
this.viewConfig = viewConfig;
126-
this.currentProps = props;
127-
this._internalInstanceHandle = internalInstanceHandle;
128-
}
129-
130-
blur() {
131-
TextInputState.blurTextInput(this);
132-
}
133-
134-
focus() {
135-
TextInputState.focusTextInput(this);
136-
}
137-
138-
measure(callback: MeasureOnSuccessCallback) {
139-
const node = getShadowNodeFromInternalInstanceHandle(
140-
this._internalInstanceHandle,
141-
);
142-
if (node != null) {
143-
fabricMeasure(node, callback);
144-
}
145-
}
146-
147-
measureInWindow(callback: MeasureInWindowOnSuccessCallback) {
148-
const node = getShadowNodeFromInternalInstanceHandle(
149-
this._internalInstanceHandle,
150-
);
151-
if (node != null) {
152-
fabricMeasureInWindow(node, callback);
153-
}
154-
}
155-
156-
measureLayout(
157-
relativeToNativeNode: number | ElementRef<HostComponent<mixed>>,
158-
onSuccess: MeasureLayoutOnSuccessCallback,
159-
onFail?: () => void /* currently unused */,
160-
) {
161-
if (
162-
typeof relativeToNativeNode === 'number' ||
163-
!(relativeToNativeNode instanceof ReactFabricHostComponent)
164-
) {
165-
if (__DEV__) {
166-
console.error(
167-
'Warning: ref.measureLayout must be called with a ref to a native component.',
168-
);
169-
}
170-
171-
return;
172-
}
173-
174-
const toStateNode = getShadowNodeFromInternalInstanceHandle(
175-
this._internalInstanceHandle,
176-
);
177-
const fromStateNode = getShadowNodeFromInternalInstanceHandle(
178-
relativeToNativeNode._internalInstanceHandle,
179-
);
180-
181-
if (toStateNode != null && fromStateNode != null) {
182-
fabricMeasureLayout(
183-
toStateNode,
184-
fromStateNode,
185-
onFail != null ? onFail : noop,
186-
onSuccess != null ? onSuccess : noop,
187-
);
188-
}
189-
}
190-
191-
unstable_getBoundingClientRect(): DOMRect {
192-
const node = getShadowNodeFromInternalInstanceHandle(
193-
this._internalInstanceHandle,
194-
);
195-
if (node != null) {
196-
const rect = fabricGetBoundingClientRect(node);
197-
198-
if (rect) {
199-
return new DOMRect(rect[0], rect[1], rect[2], rect[3]);
200-
}
201-
}
202-
203-
// Empty rect if any of the above failed
204-
return new DOMRect(0, 0, 0, 0);
205-
}
206-
207-
setNativeProps(nativeProps: Object) {
208-
if (__DEV__) {
209-
warnForStyleProps(nativeProps, this.viewConfig.validAttributes);
210-
}
211-
const updatePayload = create(nativeProps, this.viewConfig.validAttributes);
212-
213-
const node = getShadowNodeFromInternalInstanceHandle(
214-
this._internalInstanceHandle,
215-
);
216-
if (node != null && updatePayload != null) {
217-
setNativeProps(node, updatePayload);
218-
}
219-
}
220-
}
221-
222-
type ParamOf<Fn> = $Call<<T>((arg: T) => mixed) => T, Fn>;
223-
type ShadowNode = ParamOf<(typeof nativeFabricUIManager)['measure']>;
224-
225-
export function getShadowNodeFromInternalInstanceHandle(
226-
internalInstanceHandle: mixed,
227-
): ?ShadowNode {
228-
// $FlowExpectedError[incompatible-use] internalInstanceHandle is opaque but we need to make an exception here.
229-
return internalInstanceHandle?.stateNode?.node;
230-
}
231-
232101
export * from 'react-reconciler/src/ReactFiberHostConfigWithNoMutation';
233102
export * from 'react-reconciler/src/ReactFiberHostConfigWithNoHydration';
234103
export * from 'react-reconciler/src/ReactFiberHostConfigWithNoScopes';
@@ -274,16 +143,21 @@ export function createInstance(
274143
internalInstanceHandle, // internalInstanceHandle
275144
);
276145

277-
const component = new ReactFabricHostComponent(
146+
const component = createPublicInstance(
278147
tag,
279148
viewConfig,
280-
props,
281149
internalInstanceHandle,
282150
);
283151

284152
return {
285153
node: node,
286-
canonical: component,
154+
publicInstance: component,
155+
internals: {
156+
nativeTag: tag,
157+
viewConfig,
158+
currentProps: props,
159+
internalInstanceHandle,
160+
},
287161
};
288162
}
289163

@@ -353,12 +227,15 @@ export function getChildHostContext(
353227
}
354228

355229
export function getPublicInstance(instance: Instance): null | PublicInstance {
356-
if (instance.canonical) {
357-
return instance.canonical;
230+
if (instance.publicInstance != null) {
231+
return instance.publicInstance;
358232
}
359233

360-
// For compatibility with Paper
234+
// For compatibility with the legacy renderer, in case it's used with Fabric
235+
// in the same app.
236+
// $FlowExpectedError[prop-missing]
361237
if (instance._nativeTag != null) {
238+
// $FlowExpectedError[incompatible-return]
362239
return instance;
363240
}
364241

@@ -377,12 +254,12 @@ export function prepareUpdate(
377254
newProps: Props,
378255
hostContext: HostContext,
379256
): null | Object {
380-
const viewConfig = instance.canonical.viewConfig;
257+
const viewConfig = instance.internals.viewConfig;
381258
const updatePayload = diff(oldProps, newProps, viewConfig.validAttributes);
382259
// TODO: If the event handlers have changed, we need to update the current props
383260
// in the commit phase but there is no host config hook to do it yet.
384261
// So instead we hack it by updating it in the render phase.
385-
instance.canonical.currentProps = newProps;
262+
instance.internals.currentProps = newProps;
386263
return updatePayload;
387264
}
388265

@@ -461,7 +338,8 @@ export function cloneInstance(
461338
}
462339
return {
463340
node: clone,
464-
canonical: instance.canonical,
341+
publicInstance: instance.publicInstance,
342+
internals: instance.internals,
465343
};
466344
}
467345

@@ -471,15 +349,16 @@ export function cloneHiddenInstance(
471349
props: Props,
472350
internalInstanceHandle: Object,
473351
): Instance {
474-
const viewConfig = instance.canonical.viewConfig;
352+
const viewConfig = instance.internals.viewConfig;
475353
const node = instance.node;
476354
const updatePayload = create(
477355
{style: {display: 'none'}},
478356
viewConfig.validAttributes,
479357
);
480358
return {
481359
node: cloneNodeWithNewProps(node, updatePayload),
482-
canonical: instance.canonical,
360+
publicInstance: instance.publicInstance,
361+
internals: instance.internals,
483362
};
484363
}
485364

0 commit comments

Comments
 (0)