mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41334 TSIA. Changelog: [Internal] Reviewed By: robhogan Differential Revision: D51025812 fbshipit-source-id: e10d437be775a6b80946483aa96460f34927f870
315 lines
9.5 KiB
JavaScript
315 lines
9.5 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow strict
|
|
* @format
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
import type {NamedShape, PropTypeAnnotation} from '../../CodegenSchema';
|
|
import type {
|
|
BooleanTypeAnnotation,
|
|
DoubleTypeAnnotation,
|
|
FloatTypeAnnotation,
|
|
Int32TypeAnnotation,
|
|
ObjectTypeAnnotation,
|
|
ReservedPropTypeAnnotation,
|
|
StringTypeAnnotation,
|
|
} from '../../CodegenSchema';
|
|
|
|
const {getEnumName} = require('../Utils');
|
|
const {
|
|
generateStructName,
|
|
getCppTypeForAnnotation,
|
|
getEnumMaskName,
|
|
getImports,
|
|
} = require('./CppHelpers.js');
|
|
|
|
function getNativeTypeFromAnnotation(
|
|
componentName: string,
|
|
prop:
|
|
| NamedShape<PropTypeAnnotation>
|
|
| {
|
|
name: string,
|
|
typeAnnotation:
|
|
| $FlowFixMe
|
|
| DoubleTypeAnnotation
|
|
| FloatTypeAnnotation
|
|
| BooleanTypeAnnotation
|
|
| Int32TypeAnnotation
|
|
| StringTypeAnnotation
|
|
| ObjectTypeAnnotation<PropTypeAnnotation>
|
|
| ReservedPropTypeAnnotation
|
|
| {
|
|
+default: string,
|
|
+options: $ReadOnlyArray<string>,
|
|
+type: 'StringEnumTypeAnnotation',
|
|
}
|
|
| {
|
|
+elementType: ObjectTypeAnnotation<PropTypeAnnotation>,
|
|
+type: 'ArrayTypeAnnotation',
|
|
},
|
|
},
|
|
nameParts: $ReadOnlyArray<string>,
|
|
): string {
|
|
const typeAnnotation = prop.typeAnnotation;
|
|
|
|
switch (typeAnnotation.type) {
|
|
case 'BooleanTypeAnnotation':
|
|
case 'StringTypeAnnotation':
|
|
case 'Int32TypeAnnotation':
|
|
case 'DoubleTypeAnnotation':
|
|
case 'FloatTypeAnnotation':
|
|
return getCppTypeForAnnotation(typeAnnotation.type);
|
|
case 'ReservedPropTypeAnnotation':
|
|
switch (typeAnnotation.name) {
|
|
case 'ColorPrimitive':
|
|
return 'SharedColor';
|
|
case 'ImageSourcePrimitive':
|
|
return 'ImageSource';
|
|
case 'ImageRequestPrimitive':
|
|
return 'ImageRequest';
|
|
case 'PointPrimitive':
|
|
return 'Point';
|
|
case 'EdgeInsetsPrimitive':
|
|
return 'EdgeInsets';
|
|
case 'DimensionPrimitive':
|
|
return 'YGValue';
|
|
default:
|
|
(typeAnnotation.name: empty);
|
|
throw new Error('Received unknown ReservedPropTypeAnnotation');
|
|
}
|
|
case 'ArrayTypeAnnotation': {
|
|
const arrayType = typeAnnotation.elementType.type;
|
|
if (arrayType === 'ArrayTypeAnnotation') {
|
|
return `std::vector<${getNativeTypeFromAnnotation(
|
|
componentName,
|
|
{typeAnnotation: typeAnnotation.elementType, name: ''},
|
|
nameParts.concat([prop.name]),
|
|
)}>`;
|
|
}
|
|
if (arrayType === 'ObjectTypeAnnotation') {
|
|
const structName = generateStructName(
|
|
componentName,
|
|
nameParts.concat([prop.name]),
|
|
);
|
|
return `std::vector<${structName}>`;
|
|
}
|
|
if (arrayType === 'StringEnumTypeAnnotation') {
|
|
const enumName = getEnumName(componentName, prop.name);
|
|
return getEnumMaskName(enumName);
|
|
}
|
|
const itemAnnotation = getNativeTypeFromAnnotation(
|
|
componentName,
|
|
{
|
|
typeAnnotation: typeAnnotation.elementType,
|
|
name: componentName,
|
|
},
|
|
nameParts.concat([prop.name]),
|
|
);
|
|
return `std::vector<${itemAnnotation}>`;
|
|
}
|
|
case 'ObjectTypeAnnotation': {
|
|
return generateStructName(componentName, nameParts.concat([prop.name]));
|
|
}
|
|
case 'StringEnumTypeAnnotation':
|
|
return getEnumName(componentName, prop.name);
|
|
case 'Int32EnumTypeAnnotation':
|
|
return getEnumName(componentName, prop.name);
|
|
case 'MixedTypeAnnotation':
|
|
return 'folly::dynamic';
|
|
default:
|
|
(typeAnnotation: empty);
|
|
throw new Error(
|
|
`Received invalid typeAnnotation for ${componentName} prop ${prop.name}, received ${typeAnnotation.type}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// This function process some types if we need to customize them
|
|
/// For example, the ImageSource and the reserved types could be trasformed into
|
|
/// const address instead of using them as plain types.
|
|
function convertTypesToConstAddressIfNeeded(
|
|
type: string,
|
|
convertibleTypes: Set<string>,
|
|
): string {
|
|
if (convertibleTypes.has(type)) {
|
|
return `${type} const &`;
|
|
}
|
|
return type;
|
|
}
|
|
|
|
function convertValueToSharedPointerWithMove(
|
|
type: string,
|
|
value: string,
|
|
convertibleTypes: Set<string>,
|
|
): string {
|
|
if (convertibleTypes.has(type)) {
|
|
return `std::make_shared<${type}>(std::move(${value}))`;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function convertVariableToSharedPointer(
|
|
type: string,
|
|
convertibleTypes: Set<string>,
|
|
): string {
|
|
if (convertibleTypes.has(type)) {
|
|
return `std::shared_ptr<${type}>`;
|
|
}
|
|
return type;
|
|
}
|
|
|
|
function convertVariableToPointer(
|
|
type: string,
|
|
value: string,
|
|
convertibleTypes: Set<string>,
|
|
): string {
|
|
if (convertibleTypes.has(type)) {
|
|
return `*${value}`;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
const convertCtorParamToAddressType = (type: string): string => {
|
|
const typesToConvert: Set<string> = new Set();
|
|
typesToConvert.add('ImageSource');
|
|
|
|
return convertTypesToConstAddressIfNeeded(type, typesToConvert);
|
|
};
|
|
|
|
const convertCtorInitToSharedPointers = (
|
|
type: string,
|
|
value: string,
|
|
): string => {
|
|
const typesToConvert: Set<string> = new Set();
|
|
typesToConvert.add('ImageRequest');
|
|
|
|
return convertValueToSharedPointerWithMove(type, value, typesToConvert);
|
|
};
|
|
|
|
const convertGettersReturnTypeToAddressType = (type: string): string => {
|
|
const typesToConvert: Set<string> = new Set();
|
|
typesToConvert.add('ImageRequest');
|
|
|
|
return convertTypesToConstAddressIfNeeded(type, typesToConvert);
|
|
};
|
|
|
|
const convertVarTypeToSharedPointer = (type: string): string => {
|
|
const typesToConvert: Set<string> = new Set();
|
|
typesToConvert.add('ImageRequest');
|
|
|
|
return convertVariableToSharedPointer(type, typesToConvert);
|
|
};
|
|
|
|
const convertVarValueToPointer = (type: string, value: string): string => {
|
|
const typesToConvert: Set<string> = new Set();
|
|
typesToConvert.add('ImageRequest');
|
|
|
|
return convertVariableToPointer(type, value, typesToConvert);
|
|
};
|
|
|
|
function getLocalImports(
|
|
properties: $ReadOnlyArray<NamedShape<PropTypeAnnotation>>,
|
|
): Set<string> {
|
|
const imports: Set<string> = new Set();
|
|
|
|
function addImportsForNativeName(
|
|
name:
|
|
| 'ColorPrimitive'
|
|
| 'EdgeInsetsPrimitive'
|
|
| 'ImageSourcePrimitive'
|
|
| 'PointPrimitive'
|
|
| 'ImageRequestPrimitive'
|
|
| 'DimensionPrimitive',
|
|
) {
|
|
switch (name) {
|
|
case 'ColorPrimitive':
|
|
imports.add('#include <react/renderer/graphics/Color.h>');
|
|
return;
|
|
case 'ImageSourcePrimitive':
|
|
imports.add('#include <react/renderer/imagemanager/primitives.h>');
|
|
return;
|
|
case 'ImageRequestPrimitive':
|
|
imports.add('#include <react/renderer/imagemanager/ImageRequest.h>');
|
|
return;
|
|
case 'PointPrimitive':
|
|
imports.add('#include <react/renderer/graphics/Point.h>');
|
|
return;
|
|
case 'EdgeInsetsPrimitive':
|
|
imports.add('#include <react/renderer/graphics/RectangleEdges.h>');
|
|
return;
|
|
case 'DimensionPrimitive':
|
|
imports.add('#include <yoga/Yoga.h>');
|
|
return;
|
|
default:
|
|
(name: empty);
|
|
throw new Error(`Invalid ReservedPropTypeAnnotation name, got ${name}`);
|
|
}
|
|
}
|
|
|
|
properties.forEach(prop => {
|
|
const typeAnnotation = prop.typeAnnotation;
|
|
|
|
if (typeAnnotation.type === 'ReservedPropTypeAnnotation') {
|
|
addImportsForNativeName(typeAnnotation.name);
|
|
}
|
|
|
|
if (typeAnnotation.type === 'ArrayTypeAnnotation') {
|
|
imports.add('#include <vector>');
|
|
if (typeAnnotation.elementType.type === 'StringEnumTypeAnnotation') {
|
|
imports.add('#include <cinttypes>');
|
|
}
|
|
}
|
|
|
|
if (
|
|
typeAnnotation.type === 'ArrayTypeAnnotation' &&
|
|
typeAnnotation.elementType.type === 'ReservedPropTypeAnnotation'
|
|
) {
|
|
addImportsForNativeName(typeAnnotation.elementType.name);
|
|
}
|
|
|
|
if (
|
|
typeAnnotation.type === 'ArrayTypeAnnotation' &&
|
|
typeAnnotation.elementType.type === 'ObjectTypeAnnotation'
|
|
) {
|
|
imports.add('#include <react/renderer/core/propsConversions.h>');
|
|
const objectProps = typeAnnotation.elementType.properties;
|
|
// $FlowFixMe[incompatible-call] the type is guaranteed to be ObjectTypeAnnotation<PropTypeAnnotation>
|
|
const objectImports = getImports(objectProps);
|
|
// $FlowFixMe[incompatible-call] the type is guaranteed to be ObjectTypeAnnotation<PropTypeAnnotation>
|
|
const localImports = getLocalImports(objectProps);
|
|
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
|
|
objectImports.forEach(imports.add, imports);
|
|
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
|
|
localImports.forEach(imports.add, imports);
|
|
}
|
|
|
|
if (typeAnnotation.type === 'ObjectTypeAnnotation') {
|
|
imports.add('#include <react/renderer/core/propsConversions.h>');
|
|
const objectImports = getImports(typeAnnotation.properties);
|
|
const localImports = getLocalImports(typeAnnotation.properties);
|
|
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
|
|
objectImports.forEach(imports.add, imports);
|
|
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
|
|
localImports.forEach(imports.add, imports);
|
|
}
|
|
});
|
|
|
|
return imports;
|
|
}
|
|
|
|
module.exports = {
|
|
getNativeTypeFromAnnotation,
|
|
convertCtorParamToAddressType,
|
|
convertGettersReturnTypeToAddressType,
|
|
convertCtorInitToSharedPointers,
|
|
convertVarTypeToSharedPointer,
|
|
convertVarValueToPointer,
|
|
getLocalImports,
|
|
};
|