diff --git a/packages/react-native-renderer/src/ReactFabricRenderer.js b/packages/react-native-renderer/src/ReactFabricRenderer.js index b19fd3f46a6f6..007c3772e5807 100644 --- a/packages/react-native-renderer/src/ReactFabricRenderer.js +++ b/packages/react-native-renderer/src/ReactFabricRenderer.js @@ -20,7 +20,6 @@ import * as ReactNativeAttributePayload from './ReactNativeAttributePayload'; import * as ReactNativeFrameScheduling from './ReactNativeFrameScheduling'; import * as ReactNativeViewConfigRegistry from './ReactNativeViewConfigRegistry'; import ReactFiberReconciler from 'react-reconciler'; -import ReactNativeTagHandles from './ReactNativeTagHandles'; import deepFreezeAndThrowOnMutationInDev from 'deepFreezeAndThrowOnMutationInDev'; import emptyObject from 'fbjs/lib/emptyObject'; @@ -30,6 +29,12 @@ import TextInputState from 'TextInputState'; import FabricUIManager from 'FabricUIManager'; import UIManager from 'UIManager'; +// Counter for uniquely identifying views. +// % 10 === 1 means it is a rootTag. +// % 2 === 0 means it is a Fabric tag. +// This means that they never overlap. +let nextReactTag = 2; + /** * This is used for refs on host components. */ @@ -133,7 +138,9 @@ const ReactFabricRenderer = ReactFiberReconciler({ hostContext: {}, internalInstanceHandle: Object, ): Instance { - const tag = ReactNativeTagHandles.allocateTag(); + const tag = nextReactTag; + nextReactTag += 2; + const viewConfig = ReactNativeViewConfigRegistry.get(type); if (__DEV__) { @@ -171,7 +178,8 @@ const ReactFabricRenderer = ReactFiberReconciler({ hostContext: {}, internalInstanceHandle: Object, ): TextInstance { - const tag = ReactNativeTagHandles.allocateTag(); + const tag = nextReactTag; + nextReactTag += 2; const node = FabricUIManager.createNode( tag, // reactTag diff --git a/packages/react-native-renderer/src/ReactNativeEventEmitter.js b/packages/react-native-renderer/src/ReactNativeEventEmitter.js index f75cbba0679d8..e43644a620826 100644 --- a/packages/react-native-renderer/src/ReactNativeEventEmitter.js +++ b/packages/react-native-renderer/src/ReactNativeEventEmitter.js @@ -13,7 +13,6 @@ import {batchedUpdates} from 'events/ReactGenericBatching'; import warning from 'fbjs/lib/warning'; import {getInstanceFromNode} from './ReactNativeComponentTree'; -import ReactNativeTagHandles from './ReactNativeTagHandles'; import type {AnyNativeEvent} from 'events/PluginModuleType'; @@ -166,7 +165,7 @@ export function receiveTouches( let rootNodeID = null; const target = nativeEvent.target; if (target !== null && target !== undefined) { - if (target < ReactNativeTagHandles.tagsStartAt) { + if (target < 1) { if (__DEV__) { warning( false, diff --git a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js index 956336c47b88a..a6446ac261237 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js +++ b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js @@ -25,7 +25,6 @@ import { } from './ReactNativeComponentTree'; import ReactNativeFiberHostComponent from './ReactNativeFiberHostComponent'; import * as ReactNativeFrameScheduling from './ReactNativeFrameScheduling'; -import ReactNativeTagHandles from './ReactNativeTagHandles'; type Container = number; export type Instance = { @@ -36,6 +35,19 @@ export type Instance = { type Props = Object; type TextInstance = number; ++// Counter for uniquely identifying views. ++// % 10 === 1 means it is a rootTag. ++// % 2 === 0 means it is a Fabric tag. +let nextReactTag = 3; +function allocateTag() { + let tag = nextReactTag; + if (tag % 10 === 1) { + tag += 2; + } + nextReactTag = tag + 2; + return tag; +} + function recursivelyUncacheFiberNode(node: Instance | TextInstance) { if (typeof node === 'number') { // Leaf node (eg text) @@ -62,7 +74,7 @@ const NativeRenderer = ReactFiberReconciler({ hostContext: {}, internalInstanceHandle: Object, ): Instance { - const tag = ReactNativeTagHandles.allocateTag(); + const tag = allocateTag(); const viewConfig = ReactNativeViewConfigRegistry.get(type); if (__DEV__) { @@ -101,7 +113,7 @@ const NativeRenderer = ReactFiberReconciler({ hostContext: {}, internalInstanceHandle: Object, ): TextInstance { - const tag = ReactNativeTagHandles.allocateTag(); + const tag = allocateTag(); UIManager.createView( tag, // reactTag diff --git a/packages/react-native-renderer/src/ReactNativeTagHandles.js b/packages/react-native-renderer/src/ReactNativeTagHandles.js deleted file mode 100644 index 5cf29cf424a9d..0000000000000 --- a/packages/react-native-renderer/src/ReactNativeTagHandles.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -import invariant from 'fbjs/lib/invariant'; - -/** - * Keeps track of allocating and associating native "tags" which are numeric, - * unique view IDs. All the native tags are negative numbers, to avoid - * collisions, but in the JS we keep track of them as positive integers to store - * them effectively in Arrays. So we must refer to them as "inverses" of the - * native tags (that are * normally negative). - * - * It *must* be the case that every `rootNodeID` always maps to the exact same - * `tag` forever. The easiest way to accomplish this is to never delete - * anything from this table. - * Why: Because `dangerouslyReplaceNodeWithMarkupByID` relies on being able to - * unmount a component with a `rootNodeID`, then mount a new one in its place, - */ -const INITIAL_TAG_COUNT = 1; -const ReactNativeTagHandles = { - tagsStartAt: INITIAL_TAG_COUNT, - tagCount: INITIAL_TAG_COUNT, - - allocateTag: function(): number { - // Skip over root IDs as those are reserved for native - while (this.reactTagIsNativeTopRootID(ReactNativeTagHandles.tagCount)) { - ReactNativeTagHandles.tagCount++; - } - const tag = ReactNativeTagHandles.tagCount; - ReactNativeTagHandles.tagCount++; - return tag; - }, - - assertRootTag: function(tag: number): void { - invariant( - this.reactTagIsNativeTopRootID(tag), - 'Expect a native root tag, instead got %s', - tag, - ); - }, - - reactTagIsNativeTopRootID: function(reactTag: number): boolean { - // We reserve all tags that are 1 mod 10 for native root views - return reactTag % 10 === 1; - }, -}; - -export default ReactNativeTagHandles; diff --git a/packages/react-native-renderer/src/__mocks__/UIManager.js b/packages/react-native-renderer/src/__mocks__/UIManager.js index d063b3c2acc5a..4a234fbdc11ee 100644 --- a/packages/react-native-renderer/src/__mocks__/UIManager.js +++ b/packages/react-native-renderer/src/__mocks__/UIManager.js @@ -9,7 +9,6 @@ // Mock of the Native Hooks -const ReactNativeTagHandles = require('../ReactNativeTagHandles').default; const invariant = require('fbjs/lib/invariant'); // Map of viewTag -> {children: [childTag], parent: ?parentTag} @@ -18,7 +17,7 @@ let views = new Map(); function autoCreateRoot(tag) { // Seriously, this is how we distinguish roots in RN. - if (!views.has(tag) && ReactNativeTagHandles.reactTagIsNativeTopRootID(tag)) { + if (!views.has(tag) && tag % 10 === 1) { roots.push(tag); views.set(tag, { children: [],