mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add support for StringLiteralTypeAnnotation (#46827)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/46827 You can now define a native module that takes an argument that is a specific string literal: Like this: ``` export interface Spec extends TurboModule { +passString: (arg: string) => void; +passStringLiteral: (arg: 'A String Literal') => void; } ``` On the native side, this will still generate `string`, but the schema will now store the string literal, and it will be allowed in JS. This should allow more strict flow / typescript types for modules. This will also allow the compatibility check to fail if the literal changes. This is a step towards accepting a union of string literals. Changelog: [General][Added] Codegen for Native Modules now supports string literals Reviewed By: GijsWeterings Differential Revision: D63872440 fbshipit-source-id: e54b97d34af4a3d1af51727db0777f26fb7b778c
This commit is contained in:
committed by
Facebook GitHub Bot
parent
73ce1984e8
commit
d2f3f06826
@@ -290,6 +290,11 @@ export interface NativeModuleStringTypeAnnotation {
|
||||
readonly type: 'StringTypeAnnotation';
|
||||
}
|
||||
|
||||
export interface NativeModuleStringLiteralTypeAnnotation {
|
||||
readonly type: 'StringLiteralTypeAnnotation';
|
||||
readonly value: string;
|
||||
}
|
||||
|
||||
export interface NativeModuleNumberTypeAnnotation {
|
||||
readonly type: 'NumberTypeAnnotation';
|
||||
}
|
||||
@@ -371,6 +376,7 @@ export type NativeModuleEventEmitterBaseTypeAnnotation =
|
||||
| NativeModuleInt32TypeAnnotation
|
||||
| NativeModuleNumberTypeAnnotation
|
||||
| NativeModuleStringTypeAnnotation
|
||||
| NativeModuleStringLiteralTypeAnnotation
|
||||
| NativeModuleTypeAliasTypeAnnotation
|
||||
| NativeModuleGenericObjectTypeAnnotation
|
||||
| VoidTypeAnnotation;
|
||||
@@ -384,6 +390,7 @@ export type NativeModuleEventEmitterTypeAnnotation =
|
||||
|
||||
export type NativeModuleBaseTypeAnnotation =
|
||||
| NativeModuleStringTypeAnnotation
|
||||
| NativeModuleStringLiteralTypeAnnotation
|
||||
| NativeModuleNumberTypeAnnotation
|
||||
| NativeModuleInt32TypeAnnotation
|
||||
| NativeModuleDoubleTypeAnnotation
|
||||
|
||||
@@ -41,6 +41,11 @@ export type StringTypeAnnotation = $ReadOnly<{
|
||||
type: 'StringTypeAnnotation',
|
||||
}>;
|
||||
|
||||
export type StringLiteralTypeAnnotation = $ReadOnly<{
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: string,
|
||||
}>;
|
||||
|
||||
export type StringEnumTypeAnnotation = $ReadOnly<{
|
||||
type: 'StringEnumTypeAnnotation',
|
||||
options: $ReadOnlyArray<string>,
|
||||
@@ -357,6 +362,7 @@ type NativeModuleEventEmitterBaseTypeAnnotation =
|
||||
| Int32TypeAnnotation
|
||||
| NativeModuleNumberTypeAnnotation
|
||||
| StringTypeAnnotation
|
||||
| StringLiteralTypeAnnotation
|
||||
| NativeModuleTypeAliasTypeAnnotation
|
||||
| NativeModuleGenericObjectTypeAnnotation
|
||||
| VoidTypeAnnotation;
|
||||
@@ -370,6 +376,7 @@ export type NativeModuleEventEmitterTypeAnnotation =
|
||||
|
||||
export type NativeModuleBaseTypeAnnotation =
|
||||
| StringTypeAnnotation
|
||||
| StringLiteralTypeAnnotation
|
||||
| NativeModuleNumberTypeAnnotation
|
||||
| Int32TypeAnnotation
|
||||
| DoubleTypeAnnotation
|
||||
|
||||
@@ -161,6 +161,8 @@ function serializeArg(
|
||||
}
|
||||
case 'StringTypeAnnotation':
|
||||
return wrap(val => `${val}.asString(rt)`);
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
return wrap(val => `${val}.asString(rt)`);
|
||||
case 'BooleanTypeAnnotation':
|
||||
return wrap(val => `${val}.asBool()`);
|
||||
case 'EnumDeclaration':
|
||||
|
||||
@@ -173,6 +173,8 @@ function translatePrimitiveJSTypeToCpp(
|
||||
return 'void';
|
||||
case 'StringTypeAnnotation':
|
||||
return wrapOptional('jsi::String', isRequired);
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
return wrapOptional('jsi::String', isRequired);
|
||||
case 'NumberTypeAnnotation':
|
||||
return wrapOptional('double', isRequired);
|
||||
case 'DoubleTypeAnnotation':
|
||||
|
||||
+19
-1
@@ -127,9 +127,12 @@ function translateEventEmitterTypeToJavaType(
|
||||
eventEmitter: NativeModuleEventEmitterShape,
|
||||
imports: Set<string>,
|
||||
): string {
|
||||
switch (eventEmitter.typeAnnotation.typeAnnotation.type) {
|
||||
const type = eventEmitter.typeAnnotation.typeAnnotation.type;
|
||||
switch (type) {
|
||||
case 'StringTypeAnnotation':
|
||||
return 'String';
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
return 'String';
|
||||
case 'NumberTypeAnnotation':
|
||||
case 'FloatTypeAnnotation':
|
||||
case 'DoubleTypeAnnotation':
|
||||
@@ -145,7 +148,16 @@ function translateEventEmitterTypeToJavaType(
|
||||
case 'ArrayTypeAnnotation':
|
||||
imports.add('com.facebook.react.bridge.ReadableArray');
|
||||
return 'ReadableArray';
|
||||
case 'DoubleTypeAnnotation':
|
||||
case 'FloatTypeAnnotation':
|
||||
case 'Int32TypeAnnotation':
|
||||
case 'VoidTypeAnnotation':
|
||||
// TODO: Add support for these types
|
||||
throw new Error(
|
||||
`Unsupported eventType for ${eventEmitter.name}. Found: ${eventEmitter.typeAnnotation.typeAnnotation.type}`,
|
||||
);
|
||||
default:
|
||||
(type: empty);
|
||||
throw new Error(
|
||||
`Unsupported eventType for ${eventEmitter.name}. Found: ${eventEmitter.typeAnnotation.typeAnnotation.type}`,
|
||||
);
|
||||
@@ -183,6 +195,8 @@ function translateFunctionParamToJavaType(
|
||||
}
|
||||
case 'StringTypeAnnotation':
|
||||
return wrapOptional('String', isRequired);
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
return wrapOptional('String', isRequired);
|
||||
case 'NumberTypeAnnotation':
|
||||
return wrapOptional('double', isRequired);
|
||||
case 'FloatTypeAnnotation':
|
||||
@@ -273,6 +287,8 @@ function translateFunctionReturnTypeToJavaType(
|
||||
return 'void';
|
||||
case 'StringTypeAnnotation':
|
||||
return wrapOptional('String', isRequired);
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
return wrapOptional('String', isRequired);
|
||||
case 'NumberTypeAnnotation':
|
||||
return wrapOptional('double', isRequired);
|
||||
case 'FloatTypeAnnotation':
|
||||
@@ -383,6 +399,8 @@ function getFalsyReturnStatementFromReturnType(
|
||||
}
|
||||
case 'StringTypeAnnotation':
|
||||
return nullable ? 'return null;' : 'return "";';
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
return nullable ? 'return null;' : 'return "";';
|
||||
case 'ObjectTypeAnnotation':
|
||||
return 'return null;';
|
||||
case 'GenericObjectTypeAnnotation':
|
||||
|
||||
@@ -165,6 +165,8 @@ function translateReturnTypeToKind(
|
||||
return 'VoidKind';
|
||||
case 'StringTypeAnnotation':
|
||||
return 'StringKind';
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
return 'StringKind';
|
||||
case 'BooleanTypeAnnotation':
|
||||
return 'BooleanKind';
|
||||
case 'EnumDeclaration':
|
||||
@@ -244,6 +246,8 @@ function translateParamTypeToJniType(
|
||||
}
|
||||
case 'StringTypeAnnotation':
|
||||
return 'Ljava/lang/String;';
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
return 'Ljava/lang/String;';
|
||||
case 'BooleanTypeAnnotation':
|
||||
return !isRequired ? 'Ljava/lang/Boolean;' : 'Z';
|
||||
case 'EnumDeclaration':
|
||||
@@ -320,6 +324,8 @@ function translateReturnTypeToJniType(
|
||||
return 'V';
|
||||
case 'StringTypeAnnotation':
|
||||
return 'Ljava/lang/String;';
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
return 'Ljava/lang/String;';
|
||||
case 'BooleanTypeAnnotation':
|
||||
return nullable ? 'Ljava/lang/Boolean;' : 'Z';
|
||||
case 'EnumDeclaration':
|
||||
|
||||
Vendored
+2
@@ -22,6 +22,7 @@ import type {
|
||||
NativeModuleNumberTypeAnnotation,
|
||||
NativeModuleObjectTypeAnnotation,
|
||||
StringTypeAnnotation,
|
||||
StringLiteralTypeAnnotation,
|
||||
NativeModuleTypeAliasTypeAnnotation,
|
||||
Nullable,
|
||||
ReservedTypeAnnotation,
|
||||
@@ -58,6 +59,7 @@ export type StructProperty = $ReadOnly<{
|
||||
|
||||
export type StructTypeAnnotation =
|
||||
| StringTypeAnnotation
|
||||
| StringLiteralTypeAnnotation
|
||||
| NativeModuleNumberTypeAnnotation
|
||||
| Int32TypeAnnotation
|
||||
| DoubleTypeAnnotation
|
||||
|
||||
+4
@@ -94,6 +94,8 @@ function toObjCType(
|
||||
}
|
||||
case 'StringTypeAnnotation':
|
||||
return 'NSString *';
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
return 'NSString *';
|
||||
case 'NumberTypeAnnotation':
|
||||
return wrapCxxOptional('double', isRequired);
|
||||
case 'FloatTypeAnnotation':
|
||||
@@ -173,6 +175,8 @@ function toObjCValue(
|
||||
}
|
||||
case 'StringTypeAnnotation':
|
||||
return value;
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
return value;
|
||||
case 'NumberTypeAnnotation':
|
||||
return wrapPrimitive('double');
|
||||
case 'FloatTypeAnnotation':
|
||||
|
||||
+4
@@ -85,6 +85,8 @@ function toObjCType(
|
||||
}
|
||||
case 'StringTypeAnnotation':
|
||||
return 'NSString *';
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
return 'NSString *';
|
||||
case 'NumberTypeAnnotation':
|
||||
return wrapCxxOptional('double', isRequired);
|
||||
case 'FloatTypeAnnotation':
|
||||
@@ -163,6 +165,8 @@ function toObjCValue(
|
||||
}
|
||||
case 'StringTypeAnnotation':
|
||||
return RCTBridgingTo('String');
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
return RCTBridgingTo('String');
|
||||
case 'NumberTypeAnnotation':
|
||||
return RCTBridgingTo('Double');
|
||||
case 'FloatTypeAnnotation':
|
||||
|
||||
Vendored
+14
-1
@@ -15,9 +15,13 @@ const {toPascalCase} = require('../../Utils');
|
||||
function getEventEmitterTypeObjCType(
|
||||
eventEmitter: NativeModuleEventEmitterShape,
|
||||
): string {
|
||||
switch (eventEmitter.typeAnnotation.typeAnnotation.type) {
|
||||
const type = eventEmitter.typeAnnotation.typeAnnotation.type;
|
||||
|
||||
switch (type) {
|
||||
case 'StringTypeAnnotation':
|
||||
return 'NSString *_Nonnull';
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
return 'NSString *_Nonnull';
|
||||
case 'NumberTypeAnnotation':
|
||||
return 'NSNumber *_Nonnull';
|
||||
case 'BooleanTypeAnnotation':
|
||||
@@ -28,7 +32,16 @@ function getEventEmitterTypeObjCType(
|
||||
return 'NSDictionary *';
|
||||
case 'ArrayTypeAnnotation':
|
||||
return 'NSArray<id<NSObject>> *';
|
||||
case 'DoubleTypeAnnotation':
|
||||
case 'FloatTypeAnnotation':
|
||||
case 'Int32TypeAnnotation':
|
||||
case 'VoidTypeAnnotation':
|
||||
// TODO: Add support for these types
|
||||
throw new Error(
|
||||
`Unsupported eventType for ${eventEmitter.name}. Found: ${eventEmitter.typeAnnotation.typeAnnotation.type}`,
|
||||
);
|
||||
default:
|
||||
(type: empty);
|
||||
throw new Error(
|
||||
`Unsupported eventType for ${eventEmitter.name}. Found: ${eventEmitter.typeAnnotation.typeAnnotation.type}`,
|
||||
);
|
||||
|
||||
Vendored
+8
@@ -257,6 +257,8 @@ function getParamObjCType(
|
||||
}
|
||||
case 'StringTypeAnnotation':
|
||||
return notStruct(wrapOptional('NSString *', !nullable));
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
return notStruct(wrapOptional('NSString *', !nullable));
|
||||
case 'NumberTypeAnnotation':
|
||||
return notStruct(isRequired ? 'double' : 'NSNumber *');
|
||||
case 'FloatTypeAnnotation':
|
||||
@@ -330,6 +332,10 @@ function getReturnObjCType(
|
||||
// TODO: Can NSString * returns not be _Nullable?
|
||||
// In the legacy codegen, we don't surround NSSTring * with _Nullable
|
||||
return wrapOptional('NSString *', isRequired);
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
// TODO: Can NSString * returns not be _Nullable?
|
||||
// In the legacy codegen, we don't surround NSSTring * with _Nullable
|
||||
return wrapOptional('NSString *', isRequired);
|
||||
case 'NumberTypeAnnotation':
|
||||
return wrapOptional('NSNumber *', isRequired);
|
||||
case 'FloatTypeAnnotation':
|
||||
@@ -396,6 +402,8 @@ function getReturnJSType(
|
||||
return 'NumberKind';
|
||||
case 'StringTypeAnnotation':
|
||||
return 'StringKind';
|
||||
case 'StringLiteralTypeAnnotation':
|
||||
return 'StringKind';
|
||||
case 'NumberTypeAnnotation':
|
||||
return 'NumberKind';
|
||||
case 'FloatTypeAnnotation':
|
||||
|
||||
+50
@@ -2636,6 +2636,55 @@ const UNION_MODULE: SchemaType = {
|
||||
},
|
||||
};
|
||||
|
||||
const STRING_LITERALS = {
|
||||
modules: {
|
||||
NativeSampleTurboModule: {
|
||||
type: 'NativeModule',
|
||||
aliasMap: {},
|
||||
enumMap: {},
|
||||
spec: {
|
||||
eventEmitters: [
|
||||
{
|
||||
name: 'literalEvent',
|
||||
optional: false,
|
||||
typeAnnotation: {
|
||||
type: 'EventEmitterTypeAnnotation',
|
||||
typeAnnotation: {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: 'A String Literal Event',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
methods: [
|
||||
{
|
||||
name: 'getStringLiteral',
|
||||
optional: false,
|
||||
typeAnnotation: {
|
||||
type: 'FunctionTypeAnnotation',
|
||||
returnTypeAnnotation: {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: 'A String Literal Return',
|
||||
},
|
||||
params: [
|
||||
{
|
||||
name: 'literalParam',
|
||||
optional: false,
|
||||
typeAnnotation: {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: 'A String Literal Param',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
moduleName: 'SampleTurboModule',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
complex_objects: COMPLEX_OBJECTS,
|
||||
two_modules_different_files: TWO_MODULES_DIFFERENT_FILES,
|
||||
@@ -2647,4 +2696,5 @@ module.exports = {
|
||||
cxx_only_native_modules: CXX_ONLY_NATIVE_MODULES,
|
||||
SampleWithUppercaseName: SAMPLE_WITH_UPPERCASE_NAME,
|
||||
union_module: UNION_MODULE,
|
||||
string_literals: STRING_LITERALS,
|
||||
};
|
||||
|
||||
+33
@@ -655,6 +655,39 @@ NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared
|
||||
}
|
||||
|
||||
|
||||
} // namespace facebook::react
|
||||
",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GenerateModuleCpp can generate fixture string_literals 1`] = `
|
||||
Map {
|
||||
"string_literalsJSI-generated.cpp" => "/**
|
||||
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
||||
*
|
||||
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
||||
* once the code is regenerated.
|
||||
*
|
||||
* @generated by codegen project: GenerateModuleCpp.js
|
||||
*/
|
||||
|
||||
#include \\"string_literalsJSI.h\\"
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getStringLiteral(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
||||
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getStringLiteral(
|
||||
rt,
|
||||
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt)
|
||||
);
|
||||
}
|
||||
|
||||
NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
|
||||
: TurboModule(\\"SampleTurboModule\\", jsInvoker) {
|
||||
methodMap_[\\"getStringLiteral\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getStringLiteral};
|
||||
}
|
||||
|
||||
|
||||
} // namespace facebook::react
|
||||
",
|
||||
}
|
||||
|
||||
+83
@@ -2273,6 +2273,89 @@ private:
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GenerateModuleH can generate fixture string_literals 1`] = `
|
||||
Map {
|
||||
"string_literalsJSI.h" => "/**
|
||||
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
||||
*
|
||||
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
||||
* once the code is regenerated.
|
||||
*
|
||||
* @generated by codegen project: GenerateModuleH.js
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ReactCommon/TurboModule.h>
|
||||
#include <react/bridging/Bridging.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
|
||||
class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule {
|
||||
protected:
|
||||
NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker);
|
||||
|
||||
public:
|
||||
virtual jsi::String getStringLiteral(jsi::Runtime &rt, jsi::String literalParam) = 0;
|
||||
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class JSI_EXPORT NativeSampleTurboModuleCxxSpec : public TurboModule {
|
||||
public:
|
||||
jsi::Value create(jsi::Runtime &rt, const jsi::PropNameID &propName) override {
|
||||
return delegate_.create(rt, propName);
|
||||
}
|
||||
|
||||
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime& runtime) override {
|
||||
return delegate_.getPropertyNames(runtime);
|
||||
}
|
||||
|
||||
static constexpr std::string_view kModuleName = \\"SampleTurboModule\\";
|
||||
|
||||
protected:
|
||||
NativeSampleTurboModuleCxxSpec(std::shared_ptr<CallInvoker> jsInvoker)
|
||||
: TurboModule(std::string{NativeSampleTurboModuleCxxSpec::kModuleName}, jsInvoker),
|
||||
delegate_(reinterpret_cast<T*>(this), jsInvoker) {}
|
||||
|
||||
template <typename LiteralEventType> void emitLiteralEvent(LiteralEventType value) {
|
||||
static_assert(bridging::supportsFromJs<LiteralEventType, jsi::String>, \\"value cannnot be converted to jsi::String\\");
|
||||
static_cast<AsyncEventEmitter<jsi::Value>&>(*delegate_.eventEmitterMap_[\\"literalEvent\\"]).emit([jsInvoker = jsInvoker_, eventValue = value](jsi::Runtime& rt) -> jsi::Value {
|
||||
return bridging::toJs(rt, eventValue, jsInvoker);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
class Delegate : public NativeSampleTurboModuleCxxSpecJSI {
|
||||
public:
|
||||
Delegate(T *instance, std::shared_ptr<CallInvoker> jsInvoker) :
|
||||
NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {
|
||||
eventEmitterMap_[\\"literalEvent\\"] = std::make_shared<AsyncEventEmitter<jsi::Value>>();
|
||||
}
|
||||
|
||||
jsi::String getStringLiteral(jsi::Runtime &rt, jsi::String literalParam) override {
|
||||
static_assert(
|
||||
bridging::getParameterCount(&T::getStringLiteral) == 2,
|
||||
\\"Expected getStringLiteral(...) to have 2 parameters\\");
|
||||
|
||||
return bridging::callFromJs<jsi::String>(
|
||||
rt, &T::getStringLiteral, jsInvoker_, instance_, std::move(literalParam));
|
||||
}
|
||||
|
||||
private:
|
||||
friend class NativeSampleTurboModuleCxxSpec;
|
||||
T *instance_;
|
||||
};
|
||||
|
||||
Delegate delegate_;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GenerateModuleH can generate fixture two_modules_different_files 1`] = `
|
||||
Map {
|
||||
"two_modules_different_filesJSI.h" => "/**
|
||||
|
||||
+65
@@ -1096,6 +1096,71 @@ inline JS::NativeSampleTurboModule::Constants::Builder::Builder(Constants i) : _
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GenerateModuleHObjCpp can generate fixture string_literals 1`] = `
|
||||
Map {
|
||||
"string_literals.h" => "/**
|
||||
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
||||
*
|
||||
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
||||
* once the code is regenerated.
|
||||
*
|
||||
* @generated by codegen project: GenerateModuleObjCpp
|
||||
*
|
||||
* We create an umbrella header (and corresponding implementation) here since
|
||||
* Cxx compilation in BUCK has a limitation: source-code producing genrule()s
|
||||
* must have a single output. More files => more genrule()s => slower builds.
|
||||
*/
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm.
|
||||
#endif
|
||||
|
||||
// Avoid multiple includes of string_literals symbols
|
||||
#ifndef string_literals_H
|
||||
#define string_literals_H
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <RCTRequired/RCTRequired.h>
|
||||
#import <RCTTypeSafety/RCTConvertHelpers.h>
|
||||
#import <RCTTypeSafety/RCTTypedModuleConstants.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTCxxConvert.h>
|
||||
#import <React/RCTManagedPointer.h>
|
||||
#import <ReactCommon/RCTTurboModule.h>
|
||||
#import <optional>
|
||||
#import <vector>
|
||||
|
||||
|
||||
@protocol NativeSampleTurboModuleSpec <RCTBridgeModule, RCTTurboModule>
|
||||
|
||||
- (NSString *)getStringLiteral:(NSString *)literalParam;
|
||||
|
||||
@end
|
||||
|
||||
@interface NativeSampleTurboModuleSpecBase : NSObject {
|
||||
@protected
|
||||
facebook::react::EventEmitterCallback _eventEmitterCallback;
|
||||
}
|
||||
- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper;
|
||||
|
||||
- (void)emitLiteralEvent:(NSString *_Nonnull)value;
|
||||
@end
|
||||
|
||||
namespace facebook::react {
|
||||
/**
|
||||
* ObjC++ class for module 'NativeSampleTurboModule'
|
||||
*/
|
||||
class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule {
|
||||
public:
|
||||
NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms);
|
||||
};
|
||||
} // namespace facebook::react
|
||||
|
||||
#endif // string_literals_H
|
||||
",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GenerateModuleHObjCpp can generate fixture two_modules_different_files 1`] = `
|
||||
Map {
|
||||
"two_modules_different_files.h" => "/**
|
||||
|
||||
+47
@@ -511,6 +511,53 @@ public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaMo
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GenerateModuleJavaSpec can generate fixture string_literals 1`] = `
|
||||
Map {
|
||||
"java/com/facebook/fbreact/specs/NativeSampleTurboModuleSpec.java" => "
|
||||
/**
|
||||
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
||||
*
|
||||
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
||||
* once the code is regenerated.
|
||||
*
|
||||
* @generated by codegen project: GenerateModuleJavaSpec.js
|
||||
*
|
||||
* @nolint
|
||||
*/
|
||||
|
||||
package com.facebook.fbreact.specs;
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaModule implements TurboModule {
|
||||
public static final String NAME = \\"SampleTurboModule\\";
|
||||
|
||||
public NativeSampleTurboModuleSpec(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nonnull String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
protected final void emitLiteralEvent(String value) {
|
||||
mEventEmitterCallback.invoke(\\"literalEvent\\", value);
|
||||
}
|
||||
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
@DoNotStrip
|
||||
public abstract String getStringLiteral(String literalParam);
|
||||
}
|
||||
",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GenerateModuleJavaSpec can generate fixture two_modules_different_files 1`] = `
|
||||
Map {
|
||||
"java/com/facebook/fbreact/specs/NativeSampleTurboModuleSpec.java" => "
|
||||
|
||||
+40
@@ -461,6 +461,46 @@ std::shared_ptr<TurboModule> simple_native_modules_ModuleProvider(const std::str
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GenerateModuleJniCpp can generate fixture string_literals 1`] = `
|
||||
Map {
|
||||
"jni/string_literals-generated.cpp" => "
|
||||
/**
|
||||
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
||||
*
|
||||
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
||||
* once the code is regenerated.
|
||||
*
|
||||
* @generated by codegen project: GenerateModuleJniCpp.js
|
||||
*/
|
||||
|
||||
#include \\"string_literals.h\\"
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getStringLiteral(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
||||
static jmethodID cachedMethodId = nullptr;
|
||||
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, StringKind, \\"getStringLiteral\\", \\"(Ljava/lang/String;)Ljava/lang/String;\\", args, count, cachedMethodId);
|
||||
}
|
||||
|
||||
NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms)
|
||||
: JavaTurboModule(params) {
|
||||
methodMap_[\\"getStringLiteral\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getStringLiteral};
|
||||
eventEmitterMap_[\\"literalEvent\\"] = std::make_shared<AsyncEventEmitter<folly::dynamic>>();
|
||||
setEventEmitterCallback(params.instance);
|
||||
}
|
||||
|
||||
std::shared_ptr<TurboModule> string_literals_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams ¶ms) {
|
||||
if (moduleName == \\"SampleTurboModule\\") {
|
||||
return std::make_shared<NativeSampleTurboModuleSpecJSI>(params);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GenerateModuleJniCpp can generate fixture two_modules_different_files 1`] = `
|
||||
Map {
|
||||
"jni/two_modules_different_files-generated.cpp" => "
|
||||
|
||||
+74
@@ -593,6 +593,80 @@ target_compile_options(
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GenerateModuleJniH can generate fixture string_literals 1`] = `
|
||||
Map {
|
||||
"jni/string_literals.h" => "
|
||||
/**
|
||||
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
||||
*
|
||||
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
||||
* once the code is regenerated.
|
||||
*
|
||||
* @generated by codegen project: GenerateModuleJniH.js
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ReactCommon/JavaTurboModule.h>
|
||||
#include <ReactCommon/TurboModule.h>
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
/**
|
||||
* JNI C++ class for module 'NativeSampleTurboModule'
|
||||
*/
|
||||
class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public JavaTurboModule {
|
||||
public:
|
||||
NativeSampleTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms);
|
||||
};
|
||||
|
||||
|
||||
JSI_EXPORT
|
||||
std::shared_ptr<TurboModule> string_literals_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams ¶ms);
|
||||
|
||||
} // namespace facebook::react
|
||||
",
|
||||
"jni/CMakeLists.txt" => "# 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.
|
||||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
set(CMAKE_VERBOSE_MAKEFILE on)
|
||||
|
||||
file(GLOB react_codegen_SRCS CONFIGURE_DEPENDS *.cpp react/renderer/components/string_literals/*.cpp)
|
||||
|
||||
add_library(
|
||||
react_codegen_string_literals
|
||||
OBJECT
|
||||
\${react_codegen_SRCS}
|
||||
)
|
||||
|
||||
target_include_directories(react_codegen_string_literals PUBLIC . react/renderer/components/string_literals)
|
||||
|
||||
target_link_libraries(
|
||||
react_codegen_string_literals
|
||||
fbjni
|
||||
jsi
|
||||
# We need to link different libraries based on whether we are building rncore or not, that's necessary
|
||||
# because we want to break a circular dependency between react_codegen_rncore and reactnative
|
||||
reactnative
|
||||
)
|
||||
|
||||
target_compile_options(
|
||||
react_codegen_string_literals
|
||||
PRIVATE
|
||||
-DLOG_TAG=\\\\\\"ReactNative\\\\\\"
|
||||
-fexceptions
|
||||
-frtti
|
||||
-std=c++20
|
||||
-Wall
|
||||
)
|
||||
",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GenerateModuleJniH can generate fixture two_modules_different_files 1`] = `
|
||||
Map {
|
||||
"jni/two_modules_different_files.h" => "
|
||||
|
||||
+52
@@ -632,6 +632,58 @@ namespace facebook::react {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GenerateModuleMm can generate fixture string_literals 1`] = `
|
||||
Map {
|
||||
"string_literals-generated.mm" => "/**
|
||||
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
||||
*
|
||||
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
||||
* once the code is regenerated.
|
||||
*
|
||||
* @generated by codegen project: GenerateModuleObjCpp
|
||||
*
|
||||
* We create an umbrella header (and corresponding implementation) here since
|
||||
* Cxx compilation in BUCK has a limitation: source-code producing genrule()s
|
||||
* must have a single output. More files => more genrule()s => slower builds.
|
||||
*/
|
||||
|
||||
#import \\"string_literals.h\\"
|
||||
|
||||
|
||||
@implementation NativeSampleTurboModuleSpecBase
|
||||
- (void)emitLiteralEvent:(NSString *_Nonnull)value
|
||||
{
|
||||
_eventEmitterCallback(\\"literalEvent\\", value);
|
||||
}
|
||||
|
||||
- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper
|
||||
{
|
||||
_eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback);
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getStringLiteral(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
||||
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, StringKind, \\"getStringLiteral\\", @selector(getStringLiteral:), args, count);
|
||||
}
|
||||
|
||||
NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms)
|
||||
: ObjCTurboModule(params) {
|
||||
|
||||
methodMap_[\\"getStringLiteral\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getStringLiteral};
|
||||
|
||||
eventEmitterMap_[\\"literalEvent\\"] = std::make_shared<AsyncEventEmitter<id>>();
|
||||
setEventEmitterCallback([&](const std::string &name, id value) {
|
||||
static_cast<AsyncEventEmitter<id> &>(*eventEmitterMap_[name]).emit(value);
|
||||
});
|
||||
}
|
||||
} // namespace facebook::react
|
||||
",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GenerateModuleMm can generate fixture two_modules_different_files 1`] = `
|
||||
Map {
|
||||
"two_modules_different_files-generated.mm" => "/**
|
||||
|
||||
+1
@@ -128,6 +128,7 @@ export interface Spec extends TurboModule {
|
||||
+passNumber: (arg: number) => void;
|
||||
+passString: (arg: string) => void;
|
||||
+passStringish: (arg: Stringish) => void;
|
||||
+passStringLiteral: (arg: 'A String Literal') => void;
|
||||
}
|
||||
|
||||
export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
|
||||
|
||||
+22
-2
@@ -1000,6 +1000,26 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_BASIC_PA
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'passStringLiteral',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'FunctionTypeAnnotation',
|
||||
'returnTypeAnnotation': {
|
||||
'type': 'VoidTypeAnnotation'
|
||||
},
|
||||
'params': [
|
||||
{
|
||||
'name': 'arg',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'A String Literal'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2469,8 +2489,8 @@ exports[`RN Codegen Flow Parser can generate fixture PROMISE_WITH_COMMONLY_USED_
|
||||
'name': 'type',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'UnionTypeAnnotation',
|
||||
'memberType': 'StringTypeAnnotation'
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'A_String_Literal'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -244,10 +244,9 @@ function translateTypeAnnotation(
|
||||
return emitUnion(nullable, hasteModuleName, typeAnnotation, parser);
|
||||
}
|
||||
case 'StringLiteralTypeAnnotation': {
|
||||
// 'a' is a special case for 'a' | 'b' but the type name is different
|
||||
return wrapNullable(nullable, {
|
||||
type: 'UnionTypeAnnotation',
|
||||
memberType: 'StringTypeAnnotation',
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: typeAnnotation.value,
|
||||
});
|
||||
}
|
||||
case 'EnumStringBody':
|
||||
|
||||
@@ -34,6 +34,7 @@ import type {
|
||||
ObjectTypeAnnotation,
|
||||
ReservedTypeAnnotation,
|
||||
StringTypeAnnotation,
|
||||
StringLiteralTypeAnnotation,
|
||||
VoidTypeAnnotation,
|
||||
} from '../CodegenSchema';
|
||||
import type {Parser} from './parser';
|
||||
@@ -174,6 +175,16 @@ function emitString(nullable: boolean): Nullable<StringTypeAnnotation> {
|
||||
});
|
||||
}
|
||||
|
||||
function emitStringLiteral(
|
||||
nullable: boolean,
|
||||
value: string,
|
||||
): Nullable<StringLiteralTypeAnnotation> {
|
||||
return wrapNullable(nullable, {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value,
|
||||
});
|
||||
}
|
||||
|
||||
function emitStringProp(
|
||||
name: string,
|
||||
optional: boolean,
|
||||
@@ -722,6 +733,7 @@ module.exports = {
|
||||
emitString,
|
||||
emitStringish,
|
||||
emitStringProp,
|
||||
emitStringLiteral,
|
||||
emitMixed,
|
||||
emitUnion,
|
||||
emitPartial,
|
||||
|
||||
+1
@@ -115,6 +115,7 @@ export interface Spec extends TurboModule {
|
||||
readonly passNumber: (arg: number) => void;
|
||||
readonly passString: (arg: string) => void;
|
||||
readonly passStringish: (arg: Stringish) => void;
|
||||
readonly passStringLiteral: (arg: 'A String Literal') => void;
|
||||
}
|
||||
|
||||
export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
|
||||
|
||||
+20
@@ -1145,6 +1145,26 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_BA
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'passStringLiteral',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'FunctionTypeAnnotation',
|
||||
'returnTypeAnnotation': {
|
||||
'type': 'VoidTypeAnnotation'
|
||||
},
|
||||
'params': [
|
||||
{
|
||||
'name': 'arg',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'A String Literal'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -40,6 +40,7 @@ const {
|
||||
emitPromise,
|
||||
emitRootTag,
|
||||
emitUnion,
|
||||
emitStringLiteral,
|
||||
translateArrayTypeAnnotation,
|
||||
typeAliasResolution,
|
||||
typeEnumResolution,
|
||||
@@ -396,6 +397,21 @@ function translateTypeAnnotation(
|
||||
case 'TSUnionType': {
|
||||
return emitUnion(nullable, hasteModuleName, typeAnnotation, parser);
|
||||
}
|
||||
case 'TSLiteralType': {
|
||||
const literal = typeAnnotation.literal;
|
||||
switch (literal.type) {
|
||||
case 'StringLiteral': {
|
||||
return emitStringLiteral(nullable, literal.value);
|
||||
}
|
||||
default: {
|
||||
throw new UnsupportedTypeAnnotationParserError(
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
parser.language(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
default: {
|
||||
const commonType = emitCommonTypes(
|
||||
hasteModuleName,
|
||||
|
||||
Reference in New Issue
Block a user