Get rid of rootNodeIDs they're just tags now
Sebastian Markbage committed
Mar 29, 2016 at 14:57 UTC
75cec60e48c305fe89c4b528e56c780aec3524c7
15 files changed
+131
-293
src/renderers/native/NodeHandle/NodeHandle.js
deleted
-83
@@ -1,83 +0,0 @@
1
-/**
2
- * @providesModule NodeHandle
3
- */
4
-
5
- /**
6
- * A "handle" is a serializable representation of the underlying platform's
7
- * native node abstraction. This allows reasoning about nodes behind a thread
8
- * (worker) boundary. On some platforms (DOM main thread) the node handle *is*
9
- * an actual DOM node - `NodeHandle` (and potentially other libraries)
10
- * abstract away those differences so you can write code that doesn't depend
11
- * on whether or not you are running in a worker. For example, you could write
12
- * application code:
13
- *
14
- *
15
- * SomeLibrary.measureNodeHandle(myNodeHandle, cb)
16
- *
17
- * Where `measureNodeHandle` knows how to handle actual DOM nodes if running
18
- * in a worker thread, and knows how to handle numeric IDs if running in a
19
- * worker thread.
20
- *
21
- * The only other requirement of a platform/environment is that it always be
22
- * possible to extract the React rootNodeID in a blocking manner (see
23
- * `getRootNodeID`).
24
- *
25
- * +------------------+ +------------------+ +------------------+
26
- * | | | | | |
27
- * | ReactJS | | YourUtilities | | Animation Utils |
28
- * | | | | | |
29
- * +------------------+ +------------------+ +------------------+
30
- *
31
- * +------------------------------------------------------------+
32
- * | Async Platform Independent Node Interface |
33
- * +------------------------------------------------------------+
34
- * | |
35
- * | NodeIterface: |
36
- * | -measure(nodeHandle, cb) |
37
- * | -setProperties(nodeHandle, cb) |
38
- * | -manageChildren(nodeHandle, nodeHandles, cb) |
39
- * | ... |
40
- * | |
41
- * | Note: This may be a simplification. We could break up much |
42
- * | of this functionality into several smaller libraries, each |
43
- * | one requiring a . |
44
- * +------------------------------------------------------------+
45
- *
46
- * +------------------------------------------------------------+
47
- * | Platform Implementations |
48
- * | ----------------------------------------- |
49
- * | React Canvas | React DOM Worker | React DOM main |
50
- * +------------------------------------------------------------+
51
- * | | | |
52
- * |-measure(..) |-measure(..) |-measure(..) |
53
- * |-setProperties(..) |-setProperties(..) |-setProperties(..) |
54
- * |-manageChildren(..)|-manageChildren(..) |-manageChildren(..)|
55
- * | ... | ... | ... |
56
- * +-----------------------------o------------------------------+
57
- * | Worker simply ^
58
- * | marshals commands |
59
- * | to Web DOM thread. |
60
- * +---------------------+
61
- */
62
-var NodeHandle = {
63
- /**
64
- * Injection
65
- */
66
- injection: {
67
- injectImplementation: function(Impl) {
68
- NodeHandle._Implementation = Impl;
69
- }
70
- },
71
-
72
- _Implementation: null,
73
-
74
- /**
75
- * @param {NodeHandle} nodeHandle The handle to the low level resource.
76
- * @return {string} React root node ID.
77
- */
78
- getRootNodeID: function(nodeHandle) {
79
- return NodeHandle._Implementation.getRootNodeID(nodeHandle);
80
- }
81
-};
82
-
83
-module.exports = NodeHandle;
src/renderers/native/NodeHandle/UniversalWorkerNodeHandle.js
deleted
-19
@@ -1,19 +0,0 @@
1
-/**
2
- * @providesModule UniversalWorkerNodeHandle
3
- */
4
-
5
-var ReactNativeTagHandles = require('ReactNativeTagHandles');
6
-
7
-var invariant = require('invariant');
8
-
9
-var UniversalWorkerNodeHandle = {
10
- getRootNodeID: function(nodeHandle) {
11
- invariant(
12
- nodeHandle !== undefined && nodeHandle !== null && nodeHandle !== 0,
13
- 'No node handle defined'
14
- );
15
- return ReactNativeTagHandles.tagToRootNodeID[nodeHandle];
16
- }
17
-};
18
-
19
-module.exports = UniversalWorkerNodeHandle;
src/renderers/native/ReactNative/ReactNativeBaseComponent.js
+13
-28
@@ -82,17 +82,8 @@ ReactNativeBaseComponent.Mixin = {
82
var createdTags = [];
83
for (var i = 0, l = mountImages.length; i < l; i++) {
84
var mountImage = mountImages[i];
85
- var childTag = mountImage.tag;
86
- var childID = mountImage.rootNodeID;
87
- warning(
88
- mountImage && mountImage.rootNodeID && mountImage.tag,
89
- 'Mount image returned does not have required data'
90
- );
91
- ReactNativeTagHandles.associateRootNodeIDWithMountedNodeHandle(
92
- childID,
93
- childTag
94
- );
95
- createdTags[i] = mountImage.tag;
85
+ var childTag = mountImage;
86
+ createdTags[i] = childTag;
87
}
88
UIManager.setChildren(containerTag, createdTags);
89
}
@@ -126,7 +117,7 @@ ReactNativeBaseComponent.Mixin = {
117
118
if (updatePayload) {
119
UIManager.updateView(
129
- ReactNativeTagHandles.mostRecentMountedNodeHandleForRootNodeID(this._rootNodeID),
120
+ this._rootNodeID,
121
this.viewConfig.uiViewClassName,
122
updatePayload
123
);
@@ -176,7 +167,7 @@ ReactNativeBaseComponent.Mixin = {
167
* @return {null} Null.
168
*/
169
getNativeNode: function() {
179
- return null;
170
+ return this._rootNodeID;
171
},
172
173
/**
@@ -184,11 +175,13 @@ ReactNativeBaseComponent.Mixin = {
175
* @param {Transaction} transaction For creating/updating.
176
* @return {string} Unique iOS view tag.
177
*/
187
- mountComponent: function(rootID, transaction, context) {
188
- this._rootNodeID = rootID;
189
-
178
+ mountComponent: function(transaction, nativeParent, nativeContainerInfo, context) {
179
var tag = ReactNativeTagHandles.allocateTag();
180
181
+ this._rootNodeID = tag;
182
+ this._nativeParent = nativeParent;
183
+ this._nativeContainerInfo = nativeContainerInfo;
184
+
185
if (__DEV__) {
186
for (var key in this.viewConfig.validAttributes) {
187
if (this._currentElement.props.hasOwnProperty(key)) {
@@ -202,17 +195,12 @@ ReactNativeBaseComponent.Mixin = {
195
this.viewConfig.validAttributes
196
);
197
205
- var nativeTopRootID = ReactNativeTagHandles.getNativeTopRootIDFromNodeID(rootID);
206
- if (nativeTopRootID == null) {
207
- invariant(
208
- false,
209
- 'nativeTopRootID not found for tag ' + tag + ' view type ' +
210
- this.viewConfig.uiViewClassName + ' with rootID ' + rootID);
211
- }
198
+ var nativeTopRootTag = nativeContainerInfo._tag;
199
+ console.log('mountInCmp', nativeContainerInfo, nativeTopRootTag);
200
UIManager.createView(
201
tag,
202
this.viewConfig.uiViewClassName,
215
- ReactNativeTagHandles.rootNodeIDToTag[nativeTopRootID],
203
+ nativeTopRootTag,
204
updatePayload
205
);
206
@@ -223,10 +211,7 @@ ReactNativeBaseComponent.Mixin = {
211
transaction,
212
context
213
);
226
- return {
227
- rootNodeID: rootID,
228
- tag: tag
229
- };
214
+ return tag;
215
}
216
};
217
src/renderers/native/ReactNative/ReactNativeComponentEnvironment.js
+1
-1
@@ -18,7 +18,7 @@ var ReactNativeComponentEnvironment = {
18
19
processChildrenUpdates: ReactNativeDOMIDOperations.dangerouslyProcessChildrenUpdates,
20
21
- replaceNodeWithMarkupByID: ReactNativeDOMIDOperations.dangerouslyReplaceNodeWithMarkupByID,
21
+ replaceNodeWithMarkup: ReactNativeDOMIDOperations.dangerouslyReplaceNodeWithMarkupByID,
22
23
/**
24
* Nothing to do for UIKit bridge.
src/renderers/native/ReactNative/ReactNativeContainerInfo.js
new
+21
@@ -0,0 +1,21 @@
1
+/**
2
+ * Copyright (c) 2015-present, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
+ * of patent rights can be found in the PATENTS file in the same directory.
8
+ *
9
+ * @providesModule ReactNativeContainerInfo
10
+ * @flow
11
+ */
12
+'use strict';
13
+
14
+function ReactNativeContainerInfo(tag) {
15
+ var info = {
16
+ _tag: tag
17
+ };
18
+ return info;
19
+}
20
+
21
+module.exports = ReactNativeContainerInfo;
src/renderers/native/ReactNative/ReactNativeDOMIDOperations.js
+5
-6
@@ -37,7 +37,8 @@ var dangerouslyProcessChildrenUpdates = function(childrenUpdates, markupList) {
37
// containerID.
38
for (var i = 0; i < childrenUpdates.length; i++) {
39
var update = childrenUpdates[i];
40
- var containerTag = ReactNativeTagHandles.mostRecentMountedNodeHandleForRootNodeID(update.parentID);
40
+ var containerTag = update.parentID;
41
+ throw new Error('parentID is borked. See changes to multiChild');
42
var updates = byContainerTag[containerTag] || (byContainerTag[containerTag] = {});
43
if (update.type === ReactMultiChildUpdateTypes.MOVE_EXISTING) {
44
(updates.moveFromIndices || (updates.moveFromIndices = [])).push(update.fromIndex);
@@ -46,9 +47,8 @@ var dangerouslyProcessChildrenUpdates = function(childrenUpdates, markupList) {
47
(updates.removeAtIndices || (updates.removeAtIndices = [])).push(update.fromIndex);
48
} else if (update.type === ReactMultiChildUpdateTypes.INSERT_MARKUP) {
49
var mountImage = markupList[update.markupIndex];
49
- var tag = mountImage.tag;
50
+ var tag = mountImage;
51
var rootNodeID = mountImage.rootNodeID;
51
- ReactNativeTagHandles.associateRootNodeIDWithMountedNodeHandle(rootNodeID, tag);
52
(updates.addAtIndices || (updates.addAtIndices = [])).push(update.toIndex);
53
(updates.addChildTags || (updates.addChildTags = [])).push(tag);
54
}
@@ -92,9 +92,8 @@ var ReactNativeDOMIDOperations = {
92
'ReactDOMIDOperations',
93
'dangerouslyReplaceNodeWithMarkupByID',
94
function(id, mountImage) {
95
- var oldTag = ReactNativeTagHandles.mostRecentMountedNodeHandleForRootNodeID(id);
96
- UIManager.replaceExistingNonRootView(oldTag, mountImage.tag);
97
- ReactNativeTagHandles.associateRootNodeIDWithMountedNodeHandle(id, mountImage.tag);
95
+ var oldTag = id;
96
+ UIManager.replaceExistingNonRootView(oldTag, mountImage);
97
}
98
),
99
};
src/renderers/native/ReactNative/ReactNativeDefaultInjection.js
-4
@@ -22,7 +22,6 @@ var EventPluginHub = require('EventPluginHub');
22
var EventPluginUtils = require('EventPluginUtils');
23
var IOSDefaultEventPluginOrder = require('IOSDefaultEventPluginOrder');
24
var IOSNativeBridgeEventPlugin = require('IOSNativeBridgeEventPlugin');
25
-var NodeHandle = require('NodeHandle');
25
var ReactElement = require('ReactElement');
26
var ReactComponentEnvironment = require('ReactComponentEnvironment');
27
var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy');
@@ -35,7 +34,6 @@ var ReactNativeComponent = require('ReactNativeComponent');
34
var ReactSimpleEmptyComponent = require('ReactSimpleEmptyComponent');
35
var ReactUpdates = require('ReactUpdates');
36
var ResponderEventPlugin = require('ResponderEventPlugin');
38
-var UniversalWorkerNodeHandle = require('UniversalWorkerNodeHandle');
37
38
var invariant = require('invariant');
39
@@ -104,8 +102,6 @@ function inject() {
102
}
103
invariant(false, 'Expected a component class, got %s.%s', tag, info);
104
});
107
-
108
- NodeHandle.injection.injectImplementation(UniversalWorkerNodeHandle);
105
}
106
107
module.exports = {
src/renderers/native/ReactNative/ReactNativeEventEmitter.js
+2
-3
@@ -15,7 +15,6 @@ var EventPluginHub = require('EventPluginHub');
15
var EventPluginRegistry = require('EventPluginRegistry');
16
var ReactEventEmitterMixin = require('ReactEventEmitterMixin');
17
var ReactNativeTagHandles = require('ReactNativeTagHandles');
18
-var NodeHandle = require('NodeHandle');
18
var EventConstants = require('EventConstants');
19
20
var merge = require('merge');
@@ -139,7 +138,7 @@ var ReactNativeEventEmitter = merge(ReactEventEmitterMixin, {
138
topLevelType: string,
139
nativeEventParam: Object
140
) {
142
- var rootNodeID = ReactNativeTagHandles.tagToRootNodeID[tag];
141
+ var rootNodeID = tag;
142
ReactNativeEventEmitter._receiveRootNodeIDEvent(
143
rootNodeID,
144
topLevelType,
@@ -200,7 +199,7 @@ var ReactNativeEventEmitter = merge(ReactEventEmitterMixin, {
199
);
200
}
201
} else {
203
- rootNodeID = NodeHandle.getRootNodeID(target);
202
+ rootNodeID = target;
203
}
204
}
205
ReactNativeEventEmitter._receiveRootNodeIDEvent(
src/renderers/native/ReactNative/ReactNativeGlobalResponderHandler.js
+2
-3
@@ -7,7 +7,6 @@
7
* of patent rights can be found in the PATENTS file in the same directory.
8
*
9
* @providesModule ReactNativeGlobalResponderHandler
10
- * @flow
10
*/
11
'use strict';
12
@@ -15,10 +14,10 @@ var ReactNativeTagHandles = require('ReactNativeTagHandles');
14
var UIManager = require('UIManager');
15
16
var ReactNativeGlobalResponderHandler = {
18
- onChange: function(from: string, to: string, blockNativeResponder: boolean) {
17
+ onChange: function(from, to, blockNativeResponder) {
18
if (to !== null) {
19
UIManager.setJSResponder(
21
- ReactNativeTagHandles.mostRecentMountedNodeHandleForRootNodeID(to),
20
+ to._rootNodeID,
21
blockNativeResponder
22
);
23
} else {
src/renderers/native/ReactNative/ReactNativeMount.js
+35
-67
@@ -12,6 +12,7 @@
12
'use strict';
13
14
var ReactElement = require('ReactElement');
15
+var ReactNativeContainerInfo = require('ReactNativeContainerInfo');
16
var ReactNativeTagHandles = require('ReactNativeTagHandles');
17
var ReactPerf = require('ReactPerf');
18
var ReactReconciler = require('ReactReconciler');
@@ -23,10 +24,6 @@ var emptyObject = require('emptyObject');
24
var instantiateReactComponent = require('instantiateReactComponent');
25
var shouldUpdateReactComponent = require('shouldUpdateReactComponent');
26
26
-function instanceNumberToChildRootID(rootNodeID, instanceNumber) {
27
- return rootNodeID + '[' + instanceNumber + ']';
28
-}
29
-
27
/**
28
* Temporary (?) hack so that we can store all top-level pending updates on
29
* composites instead of having to worry about different types of components
@@ -47,19 +44,22 @@ TopLevelWrapper.prototype.render = function() {
44
*
45
* @param {ReactComponent} componentInstance The instance to mount.
46
* @param {number} rootID ID of the root node.
50
- * @param {number} container container element to mount into.
47
+ * @param {number} containerTag container element to mount into.
48
* @param {ReactReconcileTransaction} transaction
49
*/
50
function mountComponentIntoNode(
51
componentInstance,
55
- rootID,
56
- container,
52
+ containerTag,
53
transaction) {
54
var markup = ReactReconciler.mountComponent(
59
- componentInstance, rootID, transaction, emptyObject
55
+ componentInstance,
56
+ transaction,
57
+ null,
58
+ ReactNativeContainerInfo(containerTag),
59
+ emptyObject
60
);
61
componentInstance._renderedComponent._topLevelWrapper = componentInstance;
62
- ReactNativeMount._mountImageIntoNode(markup, container);
62
+ ReactNativeMount._mountImageIntoNode(markup, containerTag);
63
}
64
65
/**
@@ -67,19 +67,17 @@ function mountComponentIntoNode(
67
*
68
* @param {ReactComponent} componentInstance The instance to mount.
69
* @param {number} rootID ID of the root node.
70
- * @param {number} container container element to mount into.
70
+ * @param {number} containerTag container element to mount into.
71
*/
72
function batchedMountComponentIntoNode(
73
componentInstance,
74
- rootID,
75
- container) {
74
+ containerTag) {
75
var transaction = ReactUpdates.ReactReconcileTransaction.getPooled();
76
transaction.perform(
77
mountComponentIntoNode,
78
null,
79
componentInstance,
81
- rootID,
82
- container,
80
+ containerTag,
81
transaction
82
);
83
ReactUpdates.ReactReconcileTransaction.release(transaction);
@@ -90,15 +88,10 @@ function batchedMountComponentIntoNode(
88
* code between the two. For now, we'll hard code the ID logic.
89
*/
90
var ReactNativeMount = {
93
- instanceCount: 0,
94
-
91
_instancesByContainerID: {},
92
93
// these two functions are needed by React Devtools
94
findNodeHandle: require('findNodeHandle'),
99
- nativeTagToRootNodeID: function (nativeTag: number): string {
100
- return ReactNativeTagHandles.tagToRootNodeID[nativeTag];
101
- },
95
96
/**
97
* @param {ReactComponent} instance Instance to render.
@@ -119,21 +112,19 @@ var ReactNativeMount = {
112
nextElement
113
);
114
122
- var topRootNodeID = ReactNativeTagHandles.tagToRootNodeID[containerTag];
123
- if (topRootNodeID) {
124
- var prevComponent = ReactNativeMount._instancesByContainerID[topRootNodeID];
125
- if (prevComponent) {
126
- var prevWrappedElement = prevComponent._currentElement;
127
- var prevElement = prevWrappedElement.props;
128
- if (shouldUpdateReactComponent(prevElement, nextElement)) {
129
- ReactUpdateQueue.enqueueElementInternal(prevComponent, nextWrappedElement);
130
- if (callback) {
131
- ReactUpdateQueue.enqueueCallbackInternal(prevComponent, callback);
132
- }
133
- return prevComponent;
134
- } else {
135
- ReactNativeMount.unmountComponentAtNode(containerTag);
115
+ var topRootNodeID = containerTag;
116
+ var prevComponent = ReactNativeMount._instancesByContainerID[topRootNodeID];
117
+ if (prevComponent) {
118
+ var prevWrappedElement = prevComponent._currentElement;
119
+ var prevElement = prevWrappedElement.props;
120
+ if (shouldUpdateReactComponent(prevElement, nextElement)) {
121
+ ReactUpdateQueue.enqueueElementInternal(prevComponent, nextWrappedElement);
122
+ if (callback) {
123
+ ReactUpdateQueue.enqueueCallbackInternal(prevComponent, callback);
124
}
125
+ return prevComponent;
126
+ } else {
127
+ ReactNativeMount.unmountComponentAtNode(containerTag);
128
}
129
}
130
@@ -142,19 +133,10 @@ var ReactNativeMount = {
133
return;
134
}
135
145
- var topRootNodeID = ReactNativeTagHandles.allocateRootNodeIDForTag(containerTag);
146
- ReactNativeTagHandles.associateRootNodeIDWithMountedNodeHandle(
147
- topRootNodeID,
148
- containerTag
149
- );
136
+ ReactNativeTagHandles.assertRootTag(containerTag);
137
138
var instance = instantiateReactComponent(nextWrappedElement);
152
- ReactNativeMount._instancesByContainerID[topRootNodeID] = instance;
153
-
154
- var childRootNodeID = instanceNumberToChildRootID(
155
- topRootNodeID,
156
- ReactNativeMount.instanceCount++
157
- );
139
+ ReactNativeMount._instancesByContainerID[containerTag] = instance;
140
141
// The initial render is synchronous but any updates that happen during
142
// rendering, in componentWillMount or componentDidMount, will be batched
@@ -163,8 +145,7 @@ var ReactNativeMount = {
145
ReactUpdates.batchedUpdates(
146
batchedMountComponentIntoNode,
147
instance,
166
- childRootNodeID,
167
- topRootNodeID
148
+ containerTag
149
);
150
var component = instance.getPublicInstance();
151
if (callback) {
@@ -184,13 +165,10 @@ var ReactNativeMount = {
165
function(mountImage, containerID) {
166
// Since we now know that the `mountImage` has been mounted, we can
167
// mark it as such.
187
- ReactNativeTagHandles.associateRootNodeIDWithMountedNodeHandle(
188
- mountImage.rootNodeID,
189
- mountImage.tag
190
- );
168
+ var childTag = mountImage;
169
UIManager.setChildren(
192
- ReactNativeTagHandles.mostRecentMountedNodeHandleForRootNodeID(containerID),
193
- [mountImage.tag]
170
+ containerID,
171
+ [childTag]
172
);
173
}
174
),
@@ -222,13 +200,12 @@ var ReactNativeMount = {
200
return false;
201
}
202
225
- var containerID = ReactNativeTagHandles.tagToRootNodeID[containerTag];
226
- var instance = ReactNativeMount._instancesByContainerID[containerID];
203
+ var instance = ReactNativeMount._instancesByContainerID[containerTag];
204
if (!instance) {
205
return false;
206
}
230
- ReactNativeMount.unmountComponentFromNode(instance, containerID);
231
- delete ReactNativeMount._instancesByContainerID[containerID];
207
+ ReactNativeMount.unmountComponentFromNode(instance, containerTag);
208
+ delete ReactNativeMount._instancesByContainerID[containerTag];
209
return true;
210
},
211
@@ -247,18 +224,9 @@ var ReactNativeMount = {
224
) {
225
// Call back into native to remove all of the subviews from this container
226
ReactReconciler.unmountComponent(instance);
250
- var containerTag =
251
- ReactNativeTagHandles.mostRecentMountedNodeHandleForRootNodeID(containerID);
252
- UIManager.removeSubviewsFromContainerWithID(containerTag);
253
- },
254
-
255
- getNode: function(rootNodeID: string): number {
256
- return ReactNativeTagHandles.rootNodeIDToTag[rootNodeID];
257
- },
258
-
259
- getID: function(nativeTag: number): string {
260
- return ReactNativeTagHandles.tagToRootNodeID[nativeTag];
227
+ UIManager.removeSubviewsFromContainerWithID(containerID);
228
}
229
+
230
};
231
232
ReactNativeMount.renderComponent = ReactPerf.measure(
src/renderers/native/ReactNative/ReactNativeTagHandles.js
+2
-56
@@ -43,71 +43,17 @@ var ReactNativeTagHandles = {
43
return tag;
44
},
45
46
- /**
47
- * This associates the *last* observed *native* mounting between `rootNodeID`
48
- * and some `tag`. This association doesn't imply that `rootNodeID` is still
49
- * natively mounted as `tag`. The only reason why we don't clear the
50
- * association when the `rootNodeID` is unmounted, is that we don't have a
51
- * convenient time to disassociate them (otherwise we would).
52
- * `unmountComponent` isn't the correct time because that doesn't imply that
53
- * the native node has been natively unmounted.
54
- */
55
- associateRootNodeIDWithMountedNodeHandle: function(
56
- rootNodeID: ?string,
57
- tag: ?number
58
- ) {
59
- warning(rootNodeID && tag, 'Root node or tag is null when associating');
60
- if (rootNodeID && tag) {
61
- ReactNativeTagHandles.tagToRootNodeID[tag] = rootNodeID;
62
- ReactNativeTagHandles.rootNodeIDToTag[rootNodeID] = tag;
63
- }
64
- },
65
-
66
- allocateRootNodeIDForTag: function(tag: number): string {
46
+ assertRootTag: function(tag: number): void {
47
invariant(
48
this.reactTagIsNativeTopRootID(tag),
49
'Expect a native root tag, instead got ', tag
50
);
71
- return '.r[' + tag + ']' + NATIVE_TOP_ROOT_ID_SEPARATOR;
51
},
52
53
reactTagIsNativeTopRootID: function(reactTag: number): bool {
54
// We reserve all tags that are 1 mod 10 for native root views
55
return reactTag % 10 === 1;
77
- },
78
-
79
- getNativeTopRootIDFromNodeID: function(nodeID: ?string): ?string {
80
- if (!nodeID) {
81
- return null;
82
- }
83
- var index = nodeID.indexOf(NATIVE_TOP_ROOT_ID_SEPARATOR);
84
- if (index === -1) {
85
- return null;
86
- }
87
- return nodeID.substr(0, index + NATIVE_TOP_ROOT_ID_SEPARATOR.length);
88
- },
89
-
90
- /**
91
- * Returns the native `nodeHandle` (`tag`) that was most recently *natively*
92
- * mounted at the `rootNodeID`. Just because a React component has been
93
- * mounted, that doesn't mean that its native node has been mounted. The
94
- * native node is mounted when we actually make the call to insert the
95
- * `nodeHandle` (`tag`) into the native hierarchy.
96
- *
97
- * @param {string} rootNodeID Root node ID to find most recently mounted tag
98
- * for. Again, this doesn't imply that it is still currently mounted.
99
- * @return {number} Tag ID of native view for most recent mounting of
100
- * `rootNodeID`.
101
- */
102
- mostRecentMountedNodeHandleForRootNodeID: function(
103
- rootNodeID: string
104
- ): number {
105
- return ReactNativeTagHandles.rootNodeIDToTag[rootNodeID];
106
- },
107
-
108
- tagToRootNodeID: ([] : Array<string>),
109
-
110
- rootNodeIDToTag: ({} : {[key: string]: number})
56
+ }
57
};
58
59
module.exports = ReactNativeTagHandles;
src/renderers/native/ReactNative/ReactNativeTextComponent.js
+19
-20
@@ -16,38 +16,38 @@ var UIManager = require('UIManager');
16
17
var invariant = require('invariant');
18
19
-var ReactNativeTextComponent = function(props) {
20
- // This constructor and its argument is currently used by mocks.
19
+var ReactNativeTextComponent = function(text) {
20
+ // This is really a ReactText (ReactNode), not a ReactElement
21
+ this._currentElement = text;
22
+ this._stringText = '' + text;
23
+ this._nativeParent = null;
24
+ this._rootNodeID = null;
25
};
26
27
Object.assign(ReactNativeTextComponent.prototype, {
28
25
- construct: function(text) {
26
- // This is really a ReactText (ReactNode), not a ReactElement
27
- this._currentElement = text;
28
- this._stringText = '' + text;
29
- this._rootNodeID = null;
30
- },
31
-
32
- mountComponent: function(rootID, transaction, context) {
29
+ mountComponent: function(transaction, nativeParent, nativeContainerInfo, context) {
30
+ // TODO: nativeParent should have this context already. Stop abusing context.
31
invariant(
32
context.isInAParentText,
33
'RawText "' + this._stringText + '" must be wrapped in an explicit ' +
34
'<Text> component.'
35
);
38
- this._rootNodeID = rootID;
36
+ this._nativeParent = nativeParent;
37
var tag = ReactNativeTagHandles.allocateTag();
40
- var nativeTopRootID = ReactNativeTagHandles.getNativeTopRootIDFromNodeID(rootID);
38
+ this._rootNodeID = tag;
39
+ var nativeTopRootTag = nativeContainerInfo._tag;
40
UIManager.createView(
41
tag,
42
'RCTRawText',
44
- nativeTopRootID ? ReactNativeTagHandles.rootNodeIDToTag[nativeTopRootID] : null,
43
+ nativeTopRootTag,
44
{text: this._stringText}
45
);
47
- return {
48
- rootNodeID: rootID,
49
- tag: tag,
50
- };
46
+ return tag;
47
+ },
48
+
49
+ getNativeNode: function() {
50
+ return this._rootNodeID;
51
},
52
53
receiveComponent: function(nextText, transaction, context) {
@@ -56,10 +56,9 @@ Object.assign(ReactNativeTextComponent.prototype, {
56
var nextStringText = '' + nextText;
57
if (nextStringText !== this._stringText) {
58
this._stringText = nextStringText;
59
+ console.log('receiveComponent', this, this._rootNodeID);
60
UIManager.updateView(
60
- ReactNativeTagHandles.mostRecentMountedNodeHandleForRootNodeID(
61
- this._rootNodeID
62
- ),
61
+ this._rootNodeID,
62
'RCTRawText',
63
{text: this._stringText}
64
);
src/renderers/native/ReactNative/__tests__/ReactNativeMount-test.js
+27
@@ -14,11 +14,13 @@
14
var React;
15
var ReactNative;
16
var createReactNativeComponentClass;
17
+var UIManager;
18
19
describe('ReactNative', function() {
20
beforeEach(function() {
21
React = require('React');
22
ReactNative = require('ReactNative');
23
+ UIManager = require('UIManager');
24
createReactNativeComponentClass = require('createReactNativeComponentClass');
25
});
26
@@ -29,6 +31,31 @@ describe('ReactNative', function() {
31
});
32
33
ReactNative.render(<View foo="test" />, 1);
34
+ expect(UIManager.createView).toBeCalled();
35
+ expect(UIManager.setChildren).toBeCalled();
36
+ expect(UIManager.manageChildren).not.toBeCalled();
37
+ expect(UIManager.updateView).not.toBeCalled();
38
+ });
39
+
40
+ it('should be able to create and update a native component', function() {
41
+ var View = createReactNativeComponentClass({
42
+ validAttributes: { foo: true },
43
+ uiViewClassName: 'View',
44
+ });
45
+
46
+ ReactNative.render(<View foo="foo" />, 11);
47
+
48
+ expect(UIManager.createView.mock.calls.length).toBe(2);
49
+ expect(UIManager.setChildren.mock.calls.length).toBe(2);
50
+ expect(UIManager.manageChildren).not.toBeCalled();
51
+ expect(UIManager.updateView).not.toBeCalled();
52
+
53
+ ReactNative.render(<View foo="bar" />, 11);
54
+
55
+ expect(UIManager.createView.mock.calls.length).toBe(2);
56
+ expect(UIManager.setChildren.mock.calls.length).toBe(2);
57
+ expect(UIManager.manageChildren).not.toBeCalled();
58
+ expect(UIManager.updateView).toBeCalledWith(3, 'View', { foo: 'bar' });
59
});
60
61
});
src/renderers/native/ReactNative/createReactNativeComponentClass.js
+2
-1
@@ -31,7 +31,8 @@ var createReactNativeComponentClass = function(
31
var Constructor = function(element) {
32
this._currentElement = element;
33
this._topLevelWrapper = null;
34
-
34
+ this._nativeParent = null;
35
+ this._nativeContainerInfo = null;
36
this._rootNodeID = null;
37
this._renderedChildren = null;
38
};
src/renderers/native/ReactNative/findNodeHandle.js
+2
-2
@@ -79,11 +79,11 @@ function findNodeHandle(componentOrHandle: any): ?number {
79
// ReactInstanceMap.get here will always succeed for mounted components
80
var internalInstance = ReactInstanceMap.get(component);
81
if (internalInstance) {
82
- return ReactNativeTagHandles.rootNodeIDToTag[internalInstance._rootNodeID];
82
+ return internalInstance._rootNodeID;
83
} else {
84
var rootNodeID = component._rootNodeID;
85
if (rootNodeID) {
86
- return ReactNativeTagHandles.rootNodeIDToTag[rootNodeID];
86
+ return rootNodeID;
87
} else {
88
invariant(
89
(