react-native
Version:
A framework for building native apps using React
156 lines (135 loc) • 5.67 kB
JavaScript
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict-local
*/
/**
* This module is meant to be used by the React renderers to create public
* instances and get some data from them (like their instance handle / fiber).
*/
import type ReactNativeDocumentT from '../../../src/private/webapis/dom/nodes/ReactNativeDocument';
import typeof * as ReactNativeDocumentModuleT from '../../../src/private/webapis/dom/nodes/ReactNativeDocument';
import type ReactNativeElementT from '../../../src/private/webapis/dom/nodes/ReactNativeElement';
import type ReadOnlyTextT from '../../../src/private/webapis/dom/nodes/ReadOnlyText';
import typeof * as RendererProxyT from '../../ReactNative/RendererProxy';
import type {
InternalInstanceHandle,
Node,
ViewConfig,
} from '../../Renderer/shims/ReactNativeTypes';
import type {RootTag} from '../RootTag';
import type ReactFabricHostComponentT from './ReactFabricHostComponent';
import * as ReactNativeFeatureFlags from '../../../src/private/featureflags/ReactNativeFeatureFlags';
export opaque type PublicRootInstance = mixed;
// Lazy loaded to avoid evaluating the module when using the legacy renderer.
let ReactNativeDocumentModuleObject: ?ReactNativeDocumentModuleT;
let ReactFabricHostComponentClass: Class<ReactFabricHostComponentT>;
let ReactNativeElementClass: Class<ReactNativeElementT>;
let ReadOnlyTextClass: Class<ReadOnlyTextT>;
let RendererProxy: RendererProxyT;
function getReactNativeDocumentModule(): ReactNativeDocumentModuleT {
if (ReactNativeDocumentModuleObject == null) {
// We initialize this lazily to avoid a require cycle.
ReactNativeDocumentModuleObject = require('../../../src/private/webapis/dom/nodes/ReactNativeDocument');
}
return ReactNativeDocumentModuleObject;
}
function getReactNativeElementClass(): Class<ReactNativeElementT> {
if (ReactNativeElementClass == null) {
ReactNativeElementClass =
require('../../../src/private/webapis/dom/nodes/ReactNativeElement').default;
}
return ReactNativeElementClass;
}
function getReactFabricHostComponentClass(): Class<ReactFabricHostComponentT> {
if (ReactFabricHostComponentClass == null) {
ReactFabricHostComponentClass =
require('./ReactFabricHostComponent').default;
}
return ReactFabricHostComponentClass;
}
function getReadOnlyTextClass(): Class<ReadOnlyTextT> {
if (ReadOnlyTextClass == null) {
ReadOnlyTextClass =
require('../../../src/private/webapis/dom/nodes/ReadOnlyText').default;
}
return ReadOnlyTextClass;
}
export function createPublicRootInstance(rootTag: RootTag): PublicRootInstance {
if (
ReactNativeFeatureFlags.enableAccessToHostTreeInFabric() &&
ReactNativeFeatureFlags.enableDOMDocumentAPI()
) {
const ReactNativeDocumentModule = getReactNativeDocumentModule();
// $FlowExpectedError[incompatible-return]
return ReactNativeDocumentModule.createReactNativeDocument(rootTag);
}
// $FlowExpectedError[incompatible-return]
return null;
}
export function createPublicInstance(
tag: number,
viewConfig: ViewConfig,
internalInstanceHandle: InternalInstanceHandle,
ownerDocument: ReactNativeDocumentT,
): ReactFabricHostComponentT | ReactNativeElementT {
if (ReactNativeFeatureFlags.enableAccessToHostTreeInFabric()) {
const ReactNativeElement = getReactNativeElementClass();
return new ReactNativeElement(
tag,
viewConfig,
internalInstanceHandle,
ownerDocument,
);
} else {
const ReactFabricHostComponent = getReactFabricHostComponentClass();
return new ReactFabricHostComponent(
tag,
viewConfig,
internalInstanceHandle,
);
}
}
export function createPublicTextInstance(
internalInstanceHandle: InternalInstanceHandle,
ownerDocument: ReactNativeDocumentT,
): ReadOnlyTextT {
const ReadOnlyText = getReadOnlyTextClass();
return new ReadOnlyText(internalInstanceHandle, ownerDocument);
}
export function getNativeTagFromPublicInstance(
publicInstance: ReactFabricHostComponentT | ReactNativeElementT,
): number {
return publicInstance.__nativeTag;
}
export function getNodeFromPublicInstance(
publicInstance: ReactFabricHostComponentT | ReactNativeElementT,
): ?Node {
// Avoid loading ReactFabric if using an instance from the legacy renderer.
if (publicInstance.__internalInstanceHandle == null) {
return null;
}
if (RendererProxy == null) {
RendererProxy = require('../../ReactNative/RendererProxy');
}
return RendererProxy.getNodeFromInternalInstanceHandle(
// $FlowExpectedError[incompatible-call] __internalInstanceHandle is always an InternalInstanceHandle from React when we get here.
publicInstance.__internalInstanceHandle,
);
}
export function getInternalInstanceHandleFromPublicInstance(
publicInstance: ReactFabricHostComponentT | ReactNativeElementT,
): InternalInstanceHandle {
// TODO(T174762768): Remove this once OSS versions of renderers will be synced.
// $FlowExpectedError[prop-missing] Keeping this for backwards-compatibility with the renderers versions in open source.
if (publicInstance._internalInstanceHandle != null) {
// $FlowExpectedError[incompatible-return] Keeping this for backwards-compatibility with the renderers versions in open source.
return publicInstance._internalInstanceHandle;
}
// $FlowExpectedError[incompatible-return] __internalInstanceHandle is always an InternalInstanceHandle from React when we get here.
return publicInstance.__internalInstanceHandle;
}