react-native/Libraries/ReactNative/ReactNativeTagHandles.js

114 lines
4.0 KiB
JavaScript
Raw Normal View History

2015-01-30 01:10:49 +00:00
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
2015-01-30 01:10:49 +00:00
*
* @providesModule ReactNativeTagHandles
2015-03-25 02:34:12 +00:00
* @flow
2015-01-30 01:10:49 +00:00
*/
'use strict';
var invariant = require('invariant');
var warning = require('warning');
/**
* 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,
*/
var INITIAL_TAG_COUNT = 1;
var NATIVE_TOP_ROOT_ID_SEPARATOR = '{TOP_LEVEL}';
var ReactNativeTagHandles = {
2015-01-30 01:10:49 +00:00
tagsStartAt: INITIAL_TAG_COUNT,
tagCount: INITIAL_TAG_COUNT,
2015-03-25 02:34:12 +00:00
allocateTag: function(): number {
2015-01-30 01:10:49 +00:00
// Skip over root IDs as those are reserved for native
while (this.reactTagIsNativeTopRootID(ReactNativeTagHandles.tagCount)) {
ReactNativeTagHandles.tagCount++;
2015-01-30 01:10:49 +00:00
}
var tag = ReactNativeTagHandles.tagCount;
ReactNativeTagHandles.tagCount++;
2015-01-30 01:10:49 +00:00
return tag;
},
/**
* This associates the *last* observed *native* mounting between `rootNodeID`
* and some `tag`. This association doesn't imply that `rootNodeID` is still
* natively mounted as `tag`. The only reason why we don't clear the
* association when the `rootNodeID` is unmounted, is that we don't have a
* convenient time to disassociate them (otherwise we would).
* `unmountComponent` isn't the correct time because that doesn't imply that
* the native node has been natively unmounted.
*/
2015-03-25 02:34:12 +00:00
associateRootNodeIDWithMountedNodeHandle: function(
rootNodeID: ?string,
tag: ?number
) {
2015-01-30 01:10:49 +00:00
warning(rootNodeID && tag, 'Root node or tag is null when associating');
2015-03-25 02:34:12 +00:00
if (rootNodeID && tag) {
ReactNativeTagHandles.tagToRootNodeID[tag] = rootNodeID;
ReactNativeTagHandles.rootNodeIDToTag[rootNodeID] = tag;
2015-03-25 02:34:12 +00:00
}
2015-01-30 01:10:49 +00:00
},
2015-03-25 02:34:12 +00:00
allocateRootNodeIDForTag: function(tag: number): string {
2015-01-30 01:10:49 +00:00
invariant(
this.reactTagIsNativeTopRootID(tag),
'Expect a native root tag, instead got ', tag
);
return '.r[' + tag + ']' + NATIVE_TOP_ROOT_ID_SEPARATOR;
2015-01-30 01:10:49 +00:00
},
2015-03-25 02:34:12 +00:00
reactTagIsNativeTopRootID: function(reactTag: number): bool {
2015-01-30 01:10:49 +00:00
// We reserve all tags that are 1 mod 10 for native root views
return reactTag % 10 === 1;
},
getNativeTopRootIDFromNodeID: function(nodeID: ?string): ?string {
if (!nodeID) {
return null;
}
var index = nodeID.indexOf(NATIVE_TOP_ROOT_ID_SEPARATOR);
if (index === -1) {
return null;
}
return nodeID.substr(0, index + NATIVE_TOP_ROOT_ID_SEPARATOR.length);
},
2015-01-30 01:10:49 +00:00
/**
* Returns the native `nodeHandle` (`tag`) that was most recently *natively*
* mounted at the `rootNodeID`. Just because a React component has been
* mounted, that doesn't mean that its native node has been mounted. The
* native node is mounted when we actually make the call to insert the
* `nodeHandle` (`tag`) into the native hierarchy.
*
* @param {string} rootNodeID Root node ID to find most recently mounted tag
* for. Again, this doesn't imply that it is still currently mounted.
* @return {number} Tag ID of native view for most recent mounting of
* `rootNodeID`.
*/
2015-03-25 02:34:12 +00:00
mostRecentMountedNodeHandleForRootNodeID: function(
rootNodeID: string
): number {
return ReactNativeTagHandles.rootNodeIDToTag[rootNodeID];
2015-01-30 01:10:49 +00:00
},
2015-03-25 02:34:12 +00:00
tagToRootNodeID: ([] : Array<string>),
2015-01-30 01:10:49 +00:00
2015-03-25 02:34:12 +00:00
rootNodeIDToTag: ({} : {[key: string]: number})
2015-01-30 01:10:49 +00:00
};
module.exports = ReactNativeTagHandles;