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 isArray from 'shared/isArray';
    
  11. import {
    
  12.   DefaultEventPriority,
    
  13.   type EventPriority,
    
  14. } from 'react-reconciler/src/ReactEventPriorities';
    
  15. 
    
  16. export type Type = string;
    
  17. export type Props = Object;
    
  18. export type Container = {
    
  19.   children: Array<Instance | TextInstance>,
    
  20.   createNodeMock: Function,
    
  21.   tag: 'CONTAINER',
    
  22. };
    
  23. export type Instance = {
    
  24.   type: string,
    
  25.   props: Object,
    
  26.   isHidden: boolean,
    
  27.   children: Array<Instance | TextInstance>,
    
  28.   internalInstanceHandle: Object,
    
  29.   rootContainerInstance: Container,
    
  30.   tag: 'INSTANCE',
    
  31. };
    
  32. export type TextInstance = {
    
  33.   text: string,
    
  34.   isHidden: boolean,
    
  35.   tag: 'TEXT',
    
  36. };
    
  37. export type HydratableInstance = Instance | TextInstance;
    
  38. export type PublicInstance = Instance | TextInstance;
    
  39. export type HostContext = Object;
    
  40. export type UpdatePayload = Object;
    
  41. export type ChildSet = void; // Unused
    
  42. export type TimeoutHandle = TimeoutID;
    
  43. export type NoTimeout = -1;
    
  44. export type EventResponder = any;
    
  45. 
    
  46. export type RendererInspectionConfig = $ReadOnly<{}>;
    
  47. export type TransitionStatus = mixed;
    
  48. 
    
  49. export * from 'react-reconciler/src/ReactFiberConfigWithNoPersistence';
    
  50. export * from 'react-reconciler/src/ReactFiberConfigWithNoHydration';
    
  51. export * from 'react-reconciler/src/ReactFiberConfigWithNoTestSelectors';
    
  52. export * from 'react-reconciler/src/ReactFiberConfigWithNoMicrotasks';
    
  53. export * from 'react-reconciler/src/ReactFiberConfigWithNoResources';
    
  54. export * from 'react-reconciler/src/ReactFiberConfigWithNoSingletons';
    
  55. 
    
  56. const NO_CONTEXT = {};
    
  57. const nodeToInstanceMap = new WeakMap<any, Instance>();
    
  58. 
    
  59. if (__DEV__) {
    
  60.   Object.freeze(NO_CONTEXT);
    
  61. }
    
  62. 
    
  63. export function getPublicInstance(inst: Instance | TextInstance): $FlowFixMe {
    
  64.   switch (inst.tag) {
    
  65.     case 'INSTANCE':
    
  66.       const createNodeMock = inst.rootContainerInstance.createNodeMock;
    
  67.       const mockNode = createNodeMock({
    
  68.         type: inst.type,
    
  69.         props: inst.props,
    
  70.       });
    
  71.       if (typeof mockNode === 'object' && mockNode !== null) {
    
  72.         nodeToInstanceMap.set(mockNode, inst);
    
  73.       }
    
  74.       return mockNode;
    
  75.     default:
    
  76.       return inst;
    
  77.   }
    
  78. }
    
  79. 
    
  80. export function appendChild(
    
  81.   parentInstance: Instance | Container,
    
  82.   child: Instance | TextInstance,
    
  83. ): void {
    
  84.   if (__DEV__) {
    
  85.     if (!isArray(parentInstance.children)) {
    
  86.       console.error(
    
  87.         'An invalid container has been provided. ' +
    
  88.           'This may indicate that another renderer is being used in addition to the test renderer. ' +
    
  89.           '(For example, ReactDOM.createPortal inside of a ReactTestRenderer tree.) ' +
    
  90.           'This is not supported.',
    
  91.       );
    
  92.     }
    
  93.   }
    
  94.   const index = parentInstance.children.indexOf(child);
    
  95.   if (index !== -1) {
    
  96.     parentInstance.children.splice(index, 1);
    
  97.   }
    
  98.   parentInstance.children.push(child);
    
  99. }
    
  100. 
    
  101. export function insertBefore(
    
  102.   parentInstance: Instance | Container,
    
  103.   child: Instance | TextInstance,
    
  104.   beforeChild: Instance | TextInstance,
    
  105. ): void {
    
  106.   const index = parentInstance.children.indexOf(child);
    
  107.   if (index !== -1) {
    
  108.     parentInstance.children.splice(index, 1);
    
  109.   }
    
  110.   const beforeIndex = parentInstance.children.indexOf(beforeChild);
    
  111.   parentInstance.children.splice(beforeIndex, 0, child);
    
  112. }
    
  113. 
    
  114. export function removeChild(
    
  115.   parentInstance: Instance | Container,
    
  116.   child: Instance | TextInstance,
    
  117. ): void {
    
  118.   const index = parentInstance.children.indexOf(child);
    
  119.   parentInstance.children.splice(index, 1);
    
  120. }
    
  121. 
    
  122. export function clearContainer(container: Container): void {
    
  123.   container.children.splice(0);
    
  124. }
    
  125. 
    
  126. export function getRootHostContext(
    
  127.   rootContainerInstance: Container,
    
  128. ): HostContext {
    
  129.   return NO_CONTEXT;
    
  130. }
    
  131. 
    
  132. export function getChildHostContext(
    
  133.   parentHostContext: HostContext,
    
  134.   type: string,
    
  135. ): HostContext {
    
  136.   return NO_CONTEXT;
    
  137. }
    
  138. 
    
  139. export function prepareForCommit(containerInfo: Container): null | Object {
    
  140.   // noop
    
  141.   return null;
    
  142. }
    
  143. 
    
  144. export function resetAfterCommit(containerInfo: Container): void {
    
  145.   // noop
    
  146. }
    
  147. 
    
  148. export function createInstance(
    
  149.   type: string,
    
  150.   props: Props,
    
  151.   rootContainerInstance: Container,
    
  152.   hostContext: Object,
    
  153.   internalInstanceHandle: Object,
    
  154. ): Instance {
    
  155.   return {
    
  156.     type,
    
  157.     props,
    
  158.     isHidden: false,
    
  159.     children: [],
    
  160.     internalInstanceHandle,
    
  161.     rootContainerInstance,
    
  162.     tag: 'INSTANCE',
    
  163.   };
    
  164. }
    
  165. 
    
  166. export function appendInitialChild(
    
  167.   parentInstance: Instance,
    
  168.   child: Instance | TextInstance,
    
  169. ): void {
    
  170.   const index = parentInstance.children.indexOf(child);
    
  171.   if (index !== -1) {
    
  172.     parentInstance.children.splice(index, 1);
    
  173.   }
    
  174.   parentInstance.children.push(child);
    
  175. }
    
  176. 
    
  177. export function finalizeInitialChildren(
    
  178.   testElement: Instance,
    
  179.   type: string,
    
  180.   props: Props,
    
  181.   rootContainerInstance: Container,
    
  182.   hostContext: Object,
    
  183. ): boolean {
    
  184.   return false;
    
  185. }
    
  186. 
    
  187. export function shouldSetTextContent(type: string, props: Props): boolean {
    
  188.   return false;
    
  189. }
    
  190. 
    
  191. export function createTextInstance(
    
  192.   text: string,
    
  193.   rootContainerInstance: Container,
    
  194.   hostContext: Object,
    
  195.   internalInstanceHandle: Object,
    
  196. ): TextInstance {
    
  197.   return {
    
  198.     text,
    
  199.     isHidden: false,
    
  200.     tag: 'TEXT',
    
  201.   };
    
  202. }
    
  203. 
    
  204. export function getCurrentEventPriority(): EventPriority {
    
  205.   return DefaultEventPriority;
    
  206. }
    
  207. export function shouldAttemptEagerTransition(): boolean {
    
  208.   return false;
    
  209. }
    
  210. 
    
  211. export const isPrimaryRenderer = false;
    
  212. export const warnsIfNotActing = true;
    
  213. 
    
  214. export const scheduleTimeout = setTimeout;
    
  215. export const cancelTimeout = clearTimeout;
    
  216. 
    
  217. export const noTimeout = -1;
    
  218. 
    
  219. // -------------------
    
  220. //     Mutation
    
  221. // -------------------
    
  222. 
    
  223. export const supportsMutation = true;
    
  224. 
    
  225. export function commitUpdate(
    
  226.   instance: Instance,
    
  227.   updatePayload: null | {...},
    
  228.   type: string,
    
  229.   oldProps: Props,
    
  230.   newProps: Props,
    
  231.   internalInstanceHandle: Object,
    
  232. ): void {
    
  233.   instance.type = type;
    
  234.   instance.props = newProps;
    
  235. }
    
  236. 
    
  237. export function commitMount(
    
  238.   instance: Instance,
    
  239.   type: string,
    
  240.   newProps: Props,
    
  241.   internalInstanceHandle: Object,
    
  242. ): void {
    
  243.   // noop
    
  244. }
    
  245. 
    
  246. export function commitTextUpdate(
    
  247.   textInstance: TextInstance,
    
  248.   oldText: string,
    
  249.   newText: string,
    
  250. ): void {
    
  251.   textInstance.text = newText;
    
  252. }
    
  253. 
    
  254. export function resetTextContent(testElement: Instance): void {
    
  255.   // noop
    
  256. }
    
  257. 
    
  258. export const appendChildToContainer = appendChild;
    
  259. export const insertInContainerBefore = insertBefore;
    
  260. export const removeChildFromContainer = removeChild;
    
  261. 
    
  262. export function hideInstance(instance: Instance): void {
    
  263.   instance.isHidden = true;
    
  264. }
    
  265. 
    
  266. export function hideTextInstance(textInstance: TextInstance): void {
    
  267.   textInstance.isHidden = true;
    
  268. }
    
  269. 
    
  270. export function unhideInstance(instance: Instance, props: Props): void {
    
  271.   instance.isHidden = false;
    
  272. }
    
  273. 
    
  274. export function unhideTextInstance(
    
  275.   textInstance: TextInstance,
    
  276.   text: string,
    
  277. ): void {
    
  278.   textInstance.isHidden = false;
    
  279. }
    
  280. 
    
  281. export function getInstanceFromNode(mockNode: Object): Object | null {
    
  282.   const instance = nodeToInstanceMap.get(mockNode);
    
  283.   if (instance !== undefined) {
    
  284.     return instance.internalInstanceHandle;
    
  285.   }
    
  286.   return null;
    
  287. }
    
  288. 
    
  289. export function beforeActiveInstanceBlur(internalInstanceHandle: Object) {
    
  290.   // noop
    
  291. }
    
  292. 
    
  293. export function afterActiveInstanceBlur() {
    
  294.   // noop
    
  295. }
    
  296. 
    
  297. export function preparePortalMount(portalInstance: Instance): void {
    
  298.   // noop
    
  299. }
    
  300. 
    
  301. export function prepareScopeUpdate(scopeInstance: Object, inst: Object): void {
    
  302.   nodeToInstanceMap.set(scopeInstance, inst);
    
  303. }
    
  304. 
    
  305. export function getInstanceFromScope(scopeInstance: Object): null | Object {
    
  306.   return nodeToInstanceMap.get(scopeInstance) || null;
    
  307. }
    
  308. 
    
  309. export function detachDeletedInstance(node: Instance): void {
    
  310.   // noop
    
  311. }
    
  312. 
    
  313. export function logRecoverableError(error: mixed): void {
    
  314.   // noop
    
  315. }
    
  316. 
    
  317. export function requestPostPaintCallback(callback: (time: number) => void) {
    
  318.   // noop
    
  319. }
    
  320. 
    
  321. export function maySuspendCommit(type: Type, props: Props): boolean {
    
  322.   return false;
    
  323. }
    
  324. 
    
  325. export function preloadInstance(type: Type, props: Props): boolean {
    
  326.   // Return true to indicate it's already loaded
    
  327.   return true;
    
  328. }
    
  329. 
    
  330. export function startSuspendingCommit(): void {}
    
  331. 
    
  332. export function suspendInstance(type: Type, props: Props): void {}
    
  333. 
    
  334. export function waitForCommitToBeReady(): null {
    
  335.   return null;
    
  336. }
    
  337. 
    
  338. export const NotPendingTransition: TransitionStatus = null;