Skip to content

Commit d7c4136

Browse files
cipolleschifacebook-github-bot
authored andcommitted
Add ImageSource and ImageRequest to generate custom NativeState (#34910)
Summary: Pull Request resolved: #34910 This Diff adds supports on the CustomState generation for ImageSource and ImageRequests, to enable NativeComponents to use the ImageSource loading provided by React Native. To achieve this, I also had to fox some errors in the imports and to introduce some functions to decorate parameters. This diff also introduces the tests for thise additional types in both generators and parsers. ## Changelog [General][Added] - add support for ImageSource and ImageRequest in the State. Reviewed By: cortinico Differential Revision: D39884889 fbshipit-source-id: ae3d2d51dfe6a4fe688dc78fec83f428beb8d443
1 parent 7490ad4 commit d7c4136

34 files changed

+1832
-874
lines changed

packages/react-native-codegen/src/CodegenSchema.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ export type ReservedPropTypeAnnotation = $ReadOnly<{
183183
| 'ColorPrimitive'
184184
| 'ImageSourcePrimitive'
185185
| 'PointPrimitive'
186-
| 'EdgeInsetsPrimitive',
186+
| 'EdgeInsetsPrimitive'
187+
| 'ImageRequestPrimitive',
187188
}>;
188189

189190
export type StateTypeAnnotation = PropTypeAnnotation;

packages/react-native-codegen/src/generators/components/ComponentsGeneratorUtils.js

+177
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const {
3232
getEnumMaskName,
3333
getEnumName,
3434
generateStructName,
35+
getImports,
3536
} = require('./CppHelpers.js');
3637

3738
function getNativeTypeFromAnnotation(
@@ -77,6 +78,8 @@ function getNativeTypeFromAnnotation(
7778
return 'SharedColor';
7879
case 'ImageSourcePrimitive':
7980
return 'ImageSource';
81+
case 'ImageRequestPrimitive':
82+
return 'ImageRequest';
8083
case 'PointPrimitive':
8184
return 'Point';
8285
case 'EdgeInsetsPrimitive':
@@ -152,7 +155,181 @@ function getStateConstituents(
152155
};
153156
}
154157

158+
/// This function process some types if we need to customize them
159+
/// For example, the ImageSource and the reserved types could be trasformed into
160+
/// const address instead of using them as plain types.
161+
function convertTypesToConstAddressIfNeeded(
162+
type: string,
163+
convertibleTypes: Set<string>,
164+
): string {
165+
if (convertibleTypes.has(type)) {
166+
return `${type} const &`;
167+
}
168+
return type;
169+
}
170+
171+
function convertValueToSharedPointerWithMove(
172+
type: string,
173+
value: string,
174+
convertibleTypes: Set<string>,
175+
): string {
176+
if (convertibleTypes.has(type)) {
177+
return `std::make_shared<${type}>(std::move(${value}))`;
178+
}
179+
return value;
180+
}
181+
182+
function convertVariableToSharedPointer(
183+
type: string,
184+
convertibleTypes: Set<string>,
185+
): string {
186+
if (convertibleTypes.has(type)) {
187+
return `std::shared_ptr<${type}>`;
188+
}
189+
return type;
190+
}
191+
192+
function convertVariableToPointer(
193+
type: string,
194+
value: string,
195+
convertibleTypes: Set<string>,
196+
): string {
197+
if (convertibleTypes.has(type)) {
198+
return `*${value}`;
199+
}
200+
return value;
201+
}
202+
203+
const convertCtorParamToAddressType = (type: string): string => {
204+
const typesToConvert: Set<string> = new Set();
205+
typesToConvert.add('ImageSource');
206+
207+
return convertTypesToConstAddressIfNeeded(type, typesToConvert);
208+
};
209+
210+
const convertCtorInitToSharedPointers = (
211+
type: string,
212+
value: string,
213+
): string => {
214+
const typesToConvert: Set<string> = new Set();
215+
typesToConvert.add('ImageRequest');
216+
217+
return convertValueToSharedPointerWithMove(type, value, typesToConvert);
218+
};
219+
220+
const convertGettersReturnTypeToAddressType = (type: string): string => {
221+
const typesToConvert: Set<string> = new Set();
222+
typesToConvert.add('ImageRequest');
223+
224+
return convertTypesToConstAddressIfNeeded(type, typesToConvert);
225+
};
226+
227+
const convertVarTypeToSharedPointer = (type: string): string => {
228+
const typesToConvert: Set<string> = new Set();
229+
typesToConvert.add('ImageRequest');
230+
231+
return convertVariableToSharedPointer(type, typesToConvert);
232+
};
233+
234+
const convertVarValueToPointer = (type: string, value: string): string => {
235+
const typesToConvert: Set<string> = new Set();
236+
typesToConvert.add('ImageRequest');
237+
238+
return convertVariableToPointer(type, value, typesToConvert);
239+
};
240+
241+
function getLocalImports(
242+
properties:
243+
| $ReadOnlyArray<NamedShape<PropTypeAnnotation>>
244+
| $ReadOnlyArray<NamedShape<StateTypeAnnotation>>,
245+
): Set<string> {
246+
const imports: Set<string> = new Set();
247+
248+
function addImportsForNativeName(
249+
name:
250+
| 'ColorPrimitive'
251+
| 'EdgeInsetsPrimitive'
252+
| 'ImageSourcePrimitive'
253+
| 'PointPrimitive'
254+
| 'ImageRequestPrimitive',
255+
) {
256+
switch (name) {
257+
case 'ColorPrimitive':
258+
imports.add('#include <react/renderer/graphics/Color.h>');
259+
return;
260+
case 'ImageSourcePrimitive':
261+
imports.add('#include <react/renderer/imagemanager/primitives.h>');
262+
return;
263+
case 'ImageRequestPrimitive':
264+
imports.add('#include <react/renderer/imagemanager/ImageRequest.h>');
265+
return;
266+
case 'PointPrimitive':
267+
imports.add('#include <react/renderer/graphics/Geometry.h>');
268+
return;
269+
case 'EdgeInsetsPrimitive':
270+
imports.add('#include <react/renderer/graphics/Geometry.h>');
271+
return;
272+
default:
273+
(name: empty);
274+
throw new Error(`Invalid ReservedPropTypeAnnotation name, got ${name}`);
275+
}
276+
}
277+
278+
properties.forEach(prop => {
279+
const typeAnnotation = prop.typeAnnotation;
280+
281+
if (typeAnnotation.type === 'ReservedPropTypeAnnotation') {
282+
addImportsForNativeName(typeAnnotation.name);
283+
}
284+
285+
if (typeAnnotation.type === 'ArrayTypeAnnotation') {
286+
imports.add('#include <vector>');
287+
if (typeAnnotation.elementType.type === 'StringEnumTypeAnnotation') {
288+
imports.add('#include <cinttypes>');
289+
}
290+
}
291+
292+
if (
293+
typeAnnotation.type === 'ArrayTypeAnnotation' &&
294+
typeAnnotation.elementType.type === 'ReservedPropTypeAnnotation'
295+
) {
296+
addImportsForNativeName(typeAnnotation.elementType.name);
297+
}
298+
299+
if (
300+
typeAnnotation.type === 'ArrayTypeAnnotation' &&
301+
typeAnnotation.elementType.type === 'ObjectTypeAnnotation'
302+
) {
303+
const objectProps = typeAnnotation.elementType.properties;
304+
const objectImports = getImports(objectProps);
305+
const localImports = getLocalImports(objectProps);
306+
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
307+
objectImports.forEach(imports.add, imports);
308+
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
309+
localImports.forEach(imports.add, imports);
310+
}
311+
312+
if (typeAnnotation.type === 'ObjectTypeAnnotation') {
313+
imports.add('#include <react/renderer/core/propsConversions.h>');
314+
const objectImports = getImports(typeAnnotation.properties);
315+
const localImports = getLocalImports(typeAnnotation.properties);
316+
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
317+
objectImports.forEach(imports.add, imports);
318+
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
319+
localImports.forEach(imports.add, imports);
320+
}
321+
});
322+
323+
return imports;
324+
}
325+
155326
module.exports = {
156327
getNativeTypeFromAnnotation,
157328
getStateConstituents,
329+
convertCtorParamToAddressType,
330+
convertGettersReturnTypeToAddressType,
331+
convertCtorInitToSharedPointers,
332+
convertVarTypeToSharedPointer,
333+
convertVarValueToPointer,
334+
getLocalImports,
158335
};

packages/react-native-codegen/src/generators/components/CppHelpers.js

+5
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ function getImports(
6161
name:
6262
| 'ColorPrimitive'
6363
| 'EdgeInsetsPrimitive'
64+
| 'ImageRequestPrimitive'
6465
| 'ImageSourcePrimitive'
6566
| 'PointPrimitive',
6667
) {
@@ -71,6 +72,8 @@ function getImports(
7172
return;
7273
case 'EdgeInsetsPrimitive':
7374
return;
75+
case 'ImageRequestPrimitive':
76+
return;
7477
case 'ImageSourcePrimitive':
7578
imports.add('#include <react/renderer/components/image/conversions.h>');
7679
return;
@@ -163,6 +166,8 @@ function convertDefaultTypeToString(
163166
return '';
164167
case 'ImageSourcePrimitive':
165168
return '';
169+
case 'ImageRequestPrimitive':
170+
return '';
166171
case 'PointPrimitive':
167172
return '';
168173
case 'EdgeInsetsPrimitive':

packages/react-native-codegen/src/generators/components/GeneratePropsH.js

+4-81
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,17 @@
1111
'use strict';
1212
import type {ComponentShape} from '../../CodegenSchema';
1313

14-
const {getNativeTypeFromAnnotation} = require('./ComponentsGeneratorUtils.js');
14+
const {
15+
getNativeTypeFromAnnotation,
16+
getLocalImports,
17+
} = require('./ComponentsGeneratorUtils.js');
1518

1619
const {
1720
convertDefaultTypeToString,
1821
getEnumMaskName,
1922
getEnumName,
2023
toSafeCppString,
2124
generateStructName,
22-
getImports,
2325
toIntEnumValueName,
2426
} = require('./CppHelpers.js');
2527

@@ -500,85 +502,6 @@ function getExtendsImports(
500502
return imports;
501503
}
502504

503-
function getLocalImports(
504-
properties: $ReadOnlyArray<NamedShape<PropTypeAnnotation>>,
505-
): Set<string> {
506-
const imports: Set<string> = new Set();
507-
508-
function addImportsForNativeName(
509-
name:
510-
| 'ColorPrimitive'
511-
| 'EdgeInsetsPrimitive'
512-
| 'ImageSourcePrimitive'
513-
| 'PointPrimitive',
514-
) {
515-
switch (name) {
516-
case 'ColorPrimitive':
517-
imports.add('#include <react/renderer/graphics/Color.h>');
518-
return;
519-
case 'ImageSourcePrimitive':
520-
imports.add('#include <react/renderer/imagemanager/primitives.h>');
521-
return;
522-
case 'PointPrimitive':
523-
imports.add('#include <react/renderer/graphics/Geometry.h>');
524-
return;
525-
case 'EdgeInsetsPrimitive':
526-
imports.add('#include <react/renderer/graphics/Geometry.h>');
527-
return;
528-
default:
529-
(name: empty);
530-
throw new Error(`Invalid ReservedPropTypeAnnotation name, got ${name}`);
531-
}
532-
}
533-
534-
properties.forEach(prop => {
535-
const typeAnnotation = prop.typeAnnotation;
536-
537-
if (typeAnnotation.type === 'ReservedPropTypeAnnotation') {
538-
addImportsForNativeName(typeAnnotation.name);
539-
}
540-
541-
if (typeAnnotation.type === 'ArrayTypeAnnotation') {
542-
imports.add('#include <vector>');
543-
if (typeAnnotation.elementType.type === 'StringEnumTypeAnnotation') {
544-
imports.add('#include <cinttypes>');
545-
}
546-
}
547-
548-
if (
549-
typeAnnotation.type === 'ArrayTypeAnnotation' &&
550-
typeAnnotation.elementType.type === 'ReservedPropTypeAnnotation'
551-
) {
552-
addImportsForNativeName(typeAnnotation.elementType.name);
553-
}
554-
555-
if (
556-
typeAnnotation.type === 'ArrayTypeAnnotation' &&
557-
typeAnnotation.elementType.type === 'ObjectTypeAnnotation'
558-
) {
559-
const objectProps = typeAnnotation.elementType.properties;
560-
const objectImports = getImports(objectProps);
561-
const localImports = getLocalImports(objectProps);
562-
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
563-
objectImports.forEach(imports.add, imports);
564-
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
565-
localImports.forEach(imports.add, imports);
566-
}
567-
568-
if (typeAnnotation.type === 'ObjectTypeAnnotation') {
569-
imports.add('#include <react/renderer/core/propsConversions.h>');
570-
const objectImports = getImports(typeAnnotation.properties);
571-
const localImports = getLocalImports(typeAnnotation.properties);
572-
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
573-
objectImports.forEach(imports.add, imports);
574-
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
575-
localImports.forEach(imports.add, imports);
576-
}
577-
});
578-
579-
return imports;
580-
}
581-
582505
function generateStructsForComponent(
583506
componentName: string,
584507
component: ComponentShape,

packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js

+2
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ function getJavaValueForProp(
122122
return 'ColorPropConverter.getColor(value, view.getContext())';
123123
case 'ImageSourcePrimitive':
124124
return '(ReadableMap) value';
125+
case 'ImageRequestPrimitive':
126+
return '(ReadableMap) value';
125127
case 'PointPrimitive':
126128
return '(ReadableMap) value';
127129
case 'EdgeInsetsPrimitive':

packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js

+3
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ function getJavaValueForProp(
9797
case 'ImageSourcePrimitive':
9898
addNullable(imports);
9999
return '@Nullable ReadableMap value';
100+
case 'ImageRequestPrimitive':
101+
addNullable(imports);
102+
return '@Nullable ReadableMap value';
100103
case 'PointPrimitive':
101104
addNullable(imports);
102105
return '@Nullable ReadableMap value';

packages/react-native-codegen/src/generators/components/GeneratePropsJavaPojo/serializePojo.js

+11
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ function toJavaType(
8181
importReadableMap();
8282
return '@Nullable ReadableMap';
8383

84+
// TODO: Make ImageRequestPrimitive type-safe
85+
case 'ImageRequestPrimitive':
86+
importNullable();
87+
importReadableMap();
88+
return '@Nullable ReadableMap';
89+
8490
// TODO: Make PointPrimitive type-safe
8591
case 'PointPrimitive':
8692
importNullable();
@@ -162,6 +168,11 @@ function toJavaType(
162168
importReadableMap();
163169
return 'ReadableMap';
164170

171+
// TODO: Make ImageRequestPrimitive type-safe
172+
case 'ImageRequestPrimitive':
173+
importReadableMap();
174+
return 'ReadableMap';
175+
165176
// TODO: Make PointPrimitive type-safe
166177
case 'PointPrimitive':
167178
importReadableMap();

0 commit comments

Comments
 (0)