Skip to content

Commit

Permalink
Handle optional return types/values
Browse files Browse the repository at this point in the history
Summary:
Use folly to wrap optional return types and values as needed.

Changelog: [Internal]

Reviewed By: RSNara

Differential Revision: D21395439

fbshipit-source-id: a0e84e20717887e79a8565332a11fef42ebd3487
  • Loading branch information
hramos authored and facebook-github-bot committed May 8, 2020
1 parent 11b9bad commit 853dc04
Show file tree
Hide file tree
Showing 6 changed files with 309 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ function getInlineMethodSignature(
name: string,
): string {
const {typeAnnotation} = property;
function markOptionalTypeIfNecessary(type) {
if (property.optional) {
return `folly::Optional<${type}>`;
}
return type;
}
switch (typeAnnotation.type) {
case 'ReservedFunctionValueTypeAnnotation':
switch (typeAnnotation.name) {
Expand All @@ -63,18 +69,29 @@ function getInlineMethodSignature(
case 'NumberTypeAnnotation':
case 'FloatTypeAnnotation':
case 'Int32TypeAnnotation':
return `double ${property.name}() const;`;
return `${markOptionalTypeIfNecessary('double')} ${
property.name
}() const;`;
case 'BooleanTypeAnnotation':
return `bool ${property.name}() const;`;
case 'ObjectTypeAnnotation':
return `JS::Native::_MODULE_NAME_::::Spec${name}${capitalizeFirstLetter(
property.name,
)} ${property.name}() const;`;
return (
markOptionalTypeIfNecessary(
`JS::Native::_MODULE_NAME_::::Spec${name}${capitalizeFirstLetter(
property.name,
)}`,
) + ` ${property.name}() const;`
);
case 'GenericObjectTypeAnnotation':
case 'AnyTypeAnnotation':
if (property.optional) {
return `id<NSObject> _Nullable ${property.name}() const;`;
}
return `id<NSObject> ${property.name}() const;`;
case 'ArrayTypeAnnotation':
return `facebook::react::LazyVector<id<NSObject>> ${property.name}() const;`;
return `${markOptionalTypeIfNecessary(
'facebook::react::LazyVector<id<NSObject>>',
)} ${property.name}() const;`;
case 'FunctionTypeAnnotation':
default:
throw new Error(`Unknown prop type, found: ${typeAnnotation.type}"`);
Expand All @@ -86,6 +103,19 @@ function getInlineMethodImplementation(
name: string,
): string {
const {typeAnnotation} = property;
function markOptionalTypeIfNecessary(type) {
if (property.optional) {
return `folly::Optional<${type}> `;
}
return `${type} `;
}
function markOptionalValueIfNecessary(value) {
if (property.optional) {
return `RCTBridgingToOptional${capitalizeFirstLetter(value)}`;
}
return `RCTBridgingTo${capitalizeFirstLetter(value)}`;
}

switch (typeAnnotation.type) {
case 'ReservedFunctionValueTypeAnnotation':
switch (typeAnnotation.name) {
Expand All @@ -105,40 +135,59 @@ function getInlineMethodImplementation(
case 'FloatTypeAnnotation':
case 'Int32TypeAnnotation':
return inlineTemplate
.replace(/::_RETURN_TYPE_::/, 'double ')
.replace(/::_RETURN_VALUE_::/, 'RCTBridgingToDouble(p)');
.replace(/::_RETURN_TYPE_::/, markOptionalTypeIfNecessary('double'))
.replace(
/::_RETURN_VALUE_::/,
`${markOptionalValueIfNecessary('double')}(p)`,
);
case 'BooleanTypeAnnotation':
return inlineTemplate
.replace(/::_RETURN_TYPE_::/, 'bool ')
.replace(/::_RETURN_VALUE_::/, 'RCTBridgingToBool(p)');
.replace(/::_RETURN_TYPE_::/, markOptionalTypeIfNecessary('bool'))
.replace(
/::_RETURN_VALUE_::/,
`${markOptionalValueIfNecessary('bool')}(p)`,
);
case 'GenericObjectTypeAnnotation':
case 'AnyTypeAnnotation':
return inlineTemplate
.replace(/::_RETURN_TYPE_::/, 'id<NSObject> ')
.replace(
/::_RETURN_TYPE_::/,
property.optional ? 'id<NSObject> _Nullable ' : 'id<NSObject> ',
)
.replace(/::_RETURN_VALUE_::/, 'p');
case 'ObjectTypeAnnotation':
return inlineTemplate
.replace(
/::_RETURN_TYPE_::/,
`JS::Native::_MODULE_NAME_::::Spec${name}${capitalizeFirstLetter(
property.name,
)} `,
markOptionalTypeIfNecessary(
`JS::Native::_MODULE_NAME_::::Spec${name}${capitalizeFirstLetter(
property.name,
)}`,
),
)
.replace(
/::_RETURN_VALUE_::/,
`JS::Native::_MODULE_NAME_::::Spec${name}${capitalizeFirstLetter(
property.name,
)}(p)`,
property.optional
? `(p == nil ? folly::none : folly::make_optional(JS::Native::_MODULE_NAME_::::Spec${name}${capitalizeFirstLetter(
property.name,
)}(p)))`
: `JS::Native::_MODULE_NAME_::::Spec${name}${capitalizeFirstLetter(
property.name,
)}(p)`,
);
case 'ArrayTypeAnnotation':
return inlineTemplate
.replace(
/::_RETURN_TYPE_::/,
'facebook::react::LazyVector<id<NSObject>> ',
markOptionalTypeIfNecessary(
'facebook::react::LazyVector<id<NSObject>>',
),
)
.replace(
/::_RETURN_VALUE_::/,
'RCTBridgingToVec(p, ^id<NSObject>(id itemValue_0) { return itemValue_0; })',
`${markOptionalValueIfNecessary(
'vec',
)}(p, ^id<NSObject>(id itemValue_0) { return itemValue_0; })`,
);
case 'FunctionTypeAnnotation':
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,121 @@ const COMPLEX_OBJECTS: SchemaType = {
optional: false,
},
},
{
name: 'optionals',
typeAnnotation: {
type: 'FunctionTypeAnnotation',
returnTypeAnnotation: {
nullable: false,
type: 'VoidTypeAnnotation',
},
params: [
{
nullable: false,
name: 'A',
typeAnnotation: {
type: 'ObjectTypeAnnotation',
properties: [
{
optional: true,
name: 'optionalNumberProperty',
typeAnnotation: {
type: 'NumberTypeAnnotation',
},
},
{
optional: true,
name: 'optionalArrayProperty',
typeAnnotation: {
type: 'ArrayTypeAnnotation',
elementType: {
type: 'NumberTypeAnnotation',
},
},
},
{
optional: true,
name: 'optionalObjectProperty',
typeAnnotation: {
type: 'ObjectTypeAnnotation',
properties: [
{
optional: false,
name: 'x',
typeAnnotation: {
type: 'NumberTypeAnnotation',
},
},
{
optional: false,
name: 'y',
typeAnnotation: {
type: 'NumberTypeAnnotation',
},
},
],
},
},
{
optional: true,
name: 'optionalGenericObjectProperty',
typeAnnotation: {
type: 'GenericObjectTypeAnnotation',
},
},
],
},
},
],
optional: false,
},
},
{
name: 'optionalMethod',
typeAnnotation: {
type: 'FunctionTypeAnnotation',
returnTypeAnnotation: {
nullable: false,
type: 'VoidTypeAnnotation',
},
params: [
{
nullable: false,
name: 'options',
typeAnnotation: {
type: 'GenericObjectTypeAnnotation',
},
},
{
name: 'callback',
nullable: false,
typeAnnotation: {
type: 'FunctionTypeAnnotation',
},
},
{
name: 'extras',
nullable: true,
typeAnnotation: {
type: 'ArrayTypeAnnotation',
elementType: {
type: 'ObjectTypeAnnotation',
properties: [
{
optional: false,
name: 'key',
typeAnnotation: {
type: 'StringTypeAnnotation',
},
},
],
},
},
},
],
optional: true,
},
},
],
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,21 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_difficult(jsi
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->difficult(rt, args[0].getObject(rt));
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionals(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->optionals(rt, args[0].getObject(rt));
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionalMethod(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->optionalMethod(rt, args[0].getObject(rt), std::move(args[1].getObject(rt).getFunction(rt)), args[2].getObject(rt).getArray(rt));
return jsi::Value::undefined();
}
NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule(\\"SampleTurboModule\\", jsInvoker) {
methodMap_[\\"difficult\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_difficult};
methodMap_[\\"optionals\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionals};
methodMap_[\\"optionalMethod\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionalMethod};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ protected:
public:
virtual jsi::Object difficult(jsi::Runtime &rt, const jsi::Object &A) = 0;
virtual void optionals(jsi::Runtime &rt, const jsi::Object &A) = 0;
virtual void optionalMethod(jsi::Runtime &rt, const jsi::Object &options, const jsi::Function &callback, const jsi::Array &extras) = 0;
};
Expand Down
Loading

0 comments on commit 853dc04

Please sign in to comment.