Skip to content

Commit 0e1c195

Browse files
rubennortefacebook-github-bot
authored andcommitted
Improve format of mounting logs (facebook#49016)
Summary: Changelog: [internal] This replaces the existing string-based logs with something more structured, and increases the coverage to properly log all operations. As part of this work I had to refactor how we record mutations so they would be done while applying the mutations, and not before/after where necessary metadata might not be available yet/anymore. Reviewed By: sammy-SC Differential Revision: D67549201
1 parent 045edfb commit 0e1c195

File tree

6 files changed

+204
-70
lines changed

6 files changed

+204
-70
lines changed

packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-itest.js

+22-23
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ describe('focus view command', () => {
2626
Fantom.runTask(() => {
2727
root.render(
2828
<TextInput
29+
nativeID="text-input"
2930
ref={node => {
3031
if (node) {
3132
node.focus();
@@ -35,13 +36,12 @@ describe('focus view command', () => {
3536
);
3637
});
3738

38-
const mountingLogs = root.takeMountingManagerLogs();
39-
40-
expect(mountingLogs.length).toBe(2);
41-
expect(mountingLogs[0]).toBe('create view type: `AndroidTextInput`');
42-
expect(mountingLogs[1]).toBe(
43-
'dispatch command `focus` on component `AndroidTextInput`',
44-
);
39+
expect(root.takeMountingManagerLogs()).toEqual([
40+
'Update {type: "RootView", nativeID: (root)}',
41+
'Create {type: "AndroidTextInput", nativeID: "text-input"}',
42+
'Insert {type: "AndroidTextInput", parentNativeID: (root), index: 0, nativeID: "text-input"}',
43+
'Command {type: "AndroidTextInput", nativeID: "text-input", name: "focus"}',
44+
]);
4545
});
4646

4747
it('creates view before dispatching view command from useLayoutEffect', () => {
@@ -56,19 +56,18 @@ describe('focus view command', () => {
5656
textInputRef.current?.focus();
5757
});
5858

59-
return <TextInput ref={textInputRef} />;
59+
return <TextInput ref={textInputRef} nativeID="text-input" />;
6060
}
6161
Fantom.runTask(() => {
6262
root.render(<Component />);
6363
});
6464

65-
const mountingLogs = root.takeMountingManagerLogs();
66-
67-
expect(mountingLogs.length).toBe(2);
68-
expect(mountingLogs[0]).toBe('create view type: `AndroidTextInput`');
69-
expect(mountingLogs[1]).toBe(
70-
'dispatch command `focus` on component `AndroidTextInput`',
71-
);
65+
expect(root.takeMountingManagerLogs()).toEqual([
66+
'Update {type: "RootView", nativeID: (root)}',
67+
'Create {type: "AndroidTextInput", nativeID: "text-input"}',
68+
'Insert {type: "AndroidTextInput", parentNativeID: (root), index: 0, nativeID: "text-input"}',
69+
'Command {type: "AndroidTextInput", nativeID: "text-input", name: "focus"}',
70+
]);
7271
});
7372

7473
it('creates view before dispatching view command from useEffect', () => {
@@ -83,19 +82,19 @@ describe('focus view command', () => {
8382
textInputRef.current?.focus();
8483
});
8584

86-
return <TextInput ref={textInputRef} />;
85+
return <TextInput ref={textInputRef} nativeID="text-input" />;
8786
}
87+
8888
Fantom.runTask(() => {
8989
root.render(<Component />);
9090
});
9191

92-
const mountingLogs = root.takeMountingManagerLogs();
93-
94-
expect(mountingLogs.length).toBe(2);
95-
expect(mountingLogs[0]).toBe('create view type: `AndroidTextInput`');
96-
expect(mountingLogs[1]).toBe(
97-
'dispatch command `focus` on component `AndroidTextInput`',
98-
);
92+
expect(root.takeMountingManagerLogs()).toEqual([
93+
'Update {type: "RootView", nativeID: (root)}',
94+
'Create {type: "AndroidTextInput", nativeID: "text-input"}',
95+
'Insert {type: "AndroidTextInput", parentNativeID: (root), index: 0, nativeID: "text-input"}',
96+
'Command {type: "AndroidTextInput", nativeID: "text-input", name: "focus"}',
97+
]);
9998
});
10099
});
101100

packages/react-native/Libraries/ReactNative/__tests__/ReactFabric-Suspense-itest.js

+43-47
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ function Square(props: {squareId: SquareId}) {
9292
if (data == null) {
9393
data = use(fetchData(props.squareId));
9494
}
95-
return <View key={data.color} nativeID={'square with data: ' + data.color} />;
95+
return <View key={data.color} nativeID={`square-with-data-${data.color}`} />;
9696
}
9797

9898
function GreenSquare() {
@@ -104,7 +104,7 @@ function RedSquare() {
104104
}
105105

106106
function Fallback() {
107-
return <View nativeID="suspense fallback" />;
107+
return <View nativeID="suspense-fallback" />;
108108
}
109109

110110
describe('Suspense', () => {
@@ -120,25 +120,24 @@ describe('Suspense', () => {
120120
);
121121
});
122122

123-
let mountingLogs = root.takeMountingManagerLogs();
124-
125-
expect(mountingLogs.length).toBe(1);
126-
expect(mountingLogs[0]).toBe(
127-
'create view type: `View` nativeId: `suspense fallback`',
128-
);
123+
expect(root.takeMountingManagerLogs()).toEqual([
124+
'Update {type: "RootView", nativeID: (root)}',
125+
'Create {type: "View", nativeID: "suspense-fallback"}',
126+
'Insert {type: "View", parentNativeID: (root), index: 0, nativeID: "suspense-fallback"}',
127+
]);
129128

130129
expect(resolveFunction).not.toBeNull();
131130
Fantom.runTask(() => {
132131
resolveFunction?.();
133132
resolveFunction = null;
134133
});
135134

136-
mountingLogs = root.takeMountingManagerLogs();
137-
138-
expect(mountingLogs.length).toBe(1);
139-
expect(mountingLogs[0]).toBe(
140-
'create view type: `View` nativeId: `square with data: green`',
141-
);
135+
expect(root.takeMountingManagerLogs()).toEqual([
136+
'Remove {type: "View", parentNativeID: (root), index: 0, nativeID: "suspense-fallback"}',
137+
'Delete {type: "View", nativeID: "suspense-fallback"}',
138+
'Create {type: "View", nativeID: "square-with-data-green"}',
139+
'Insert {type: "View", parentNativeID: (root), index: 0, nativeID: "square-with-data-green"}',
140+
]);
142141

143142
Fantom.runTask(() => {
144143
root.render(
@@ -148,25 +147,25 @@ describe('Suspense', () => {
148147
);
149148
});
150149

151-
mountingLogs = root.takeMountingManagerLogs();
152-
153-
expect(mountingLogs.length).toBe(1);
154-
expect(mountingLogs[0]).toBe(
155-
'create view type: `View` nativeId: `suspense fallback`',
156-
);
150+
expect(root.takeMountingManagerLogs()).toEqual([
151+
'Remove {type: "View", parentNativeID: (root), index: 0, nativeID: "square-with-data-green"}',
152+
'Delete {type: "View", nativeID: "square-with-data-green"}',
153+
'Create {type: "View", nativeID: "suspense-fallback"}',
154+
'Insert {type: "View", parentNativeID: (root), index: 0, nativeID: "suspense-fallback"}',
155+
]);
157156

158157
expect(resolveFunction).not.toBeNull();
159158
Fantom.runTask(() => {
160159
resolveFunction?.();
161160
resolveFunction = null;
162161
});
163162

164-
mountingLogs = root.takeMountingManagerLogs();
165-
166-
expect(mountingLogs.length).toBe(1);
167-
expect(mountingLogs[0]).toBe(
168-
'create view type: `View` nativeId: `square with data: red`',
169-
);
163+
expect(root.takeMountingManagerLogs()).toEqual([
164+
'Remove {type: "View", parentNativeID: (root), index: 0, nativeID: "suspense-fallback"}',
165+
'Delete {type: "View", nativeID: "suspense-fallback"}',
166+
'Create {type: "View", nativeID: "square-with-data-red"}',
167+
'Insert {type: "View", parentNativeID: (root), index: 0, nativeID: "square-with-data-red"}',
168+
]);
170169

171170
Fantom.runTask(() => {
172171
root.render(
@@ -176,12 +175,12 @@ describe('Suspense', () => {
176175
);
177176
});
178177

179-
mountingLogs = root.takeMountingManagerLogs();
180-
181-
expect(mountingLogs.length).toBe(1);
182-
expect(mountingLogs[0]).toBe(
183-
'create view type: `View` nativeId: `square with data: green`',
184-
);
178+
expect(root.takeMountingManagerLogs()).toEqual([
179+
'Remove {type: "View", parentNativeID: (root), index: 0, nativeID: "square-with-data-red"}',
180+
'Delete {type: "View", nativeID: "square-with-data-red"}',
181+
'Create {type: "View", nativeID: "square-with-data-green"}',
182+
'Insert {type: "View", parentNativeID: (root), index: 0, nativeID: "square-with-data-green"}',
183+
]);
185184

186185
expect(resolveFunction).toBeNull();
187186
});
@@ -206,12 +205,11 @@ describe('Suspense', () => {
206205
root.render(<App color="green" />);
207206
});
208207

209-
let mountingLogs = root.takeMountingManagerLogs();
210-
211-
expect(mountingLogs.length).toBe(1);
212-
expect(mountingLogs[0]).toBe(
213-
'create view type: `View` nativeId: `square with data: green`',
214-
);
208+
expect(root.takeMountingManagerLogs()).toEqual([
209+
'Update {type: "RootView", nativeID: (root)}',
210+
'Create {type: "View", nativeID: "square-with-data-green"}',
211+
'Insert {type: "View", parentNativeID: (root), index: 0, nativeID: "square-with-data-green"}',
212+
]);
215213

216214
expect(resolveFunction).toBeNull();
217215
Fantom.runTask(() => {
@@ -220,22 +218,20 @@ describe('Suspense', () => {
220218
});
221219
});
222220

223-
mountingLogs = root.takeMountingManagerLogs();
224-
225221
// Green square is still mounted. Fallback is not shown to the user.
226-
expect(mountingLogs.length).toBe(0);
222+
expect(root.takeMountingManagerLogs()).toEqual([]);
227223

228224
expect(resolveFunction).not.toBeNull();
229225
Fantom.runTask(() => {
230226
resolveFunction?.();
231227
resolveFunction = null;
232228
});
233229

234-
mountingLogs = root.takeMountingManagerLogs();
235-
236-
expect(mountingLogs.length).toBe(1);
237-
expect(mountingLogs[0]).toBe(
238-
'create view type: `View` nativeId: `square with data: red`',
239-
);
230+
expect(root.takeMountingManagerLogs()).toEqual([
231+
'Remove {type: "View", parentNativeID: (root), index: 0, nativeID: "square-with-data-green"}',
232+
'Delete {type: "View", nativeID: "square-with-data-green"}',
233+
'Create {type: "View", nativeID: "square-with-data-red"}',
234+
'Insert {type: "View", parentNativeID: (root), index: 0, nativeID: "square-with-data-red"}',
235+
]);
240236
});
241237
});

packages/react-native/ReactCommon/react/renderer/mounting/stubs/StubView.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ StubView::operator ShadowView() const {
2323
shadowView.eventEmitter = eventEmitter;
2424
shadowView.layoutMetrics = layoutMetrics;
2525
shadowView.state = state;
26+
shadowView.traits = traits;
2627
return shadowView;
2728
}
2829

@@ -35,6 +36,7 @@ void StubView::update(const ShadowView& shadowView) {
3536
eventEmitter = shadowView.eventEmitter;
3637
layoutMetrics = shadowView.layoutMetrics;
3738
state = shadowView.state;
39+
traits = shadowView.traits;
3840
}
3941

4042
bool operator==(const StubView& lhs, const StubView& rhs) {

packages/react-native/ReactCommon/react/renderer/mounting/stubs/StubView.h

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class StubView final {
3434
ComponentHandle componentHandle;
3535
SurfaceId surfaceId;
3636
Tag tag;
37+
ShadowNodeTraits traits{};
3738
Props::Shared props;
3839
SharedEventEmitter eventEmitter;
3940
LayoutMetrics layoutMetrics;

0 commit comments

Comments
 (0)