Codegen: Generate module C++ lookup function for JNI next to the spec classes

Summary:
The TurboModule system requires a lookup function to map the spec name (name used in JS) to the C++ TurboModule subclass. This is a pure C function. For now, generate one lookup function per set of modules found in the codegen schema.

Changelog: [Internal]

Reviewed By: hramos

Differential Revision: D23618281

fbshipit-source-id: 889e07bdd4f2e5e93c4d14e60225f5b0c6683917
This commit is contained in:
Kevin Gozali 2020-09-11 01:12:25 -07:00 коммит произвёл Facebook GitHub Bot
Родитель e26c280782
Коммит 0351c57e6a
8 изменённых файлов: 122 добавлений и 19 удалений

2
.gitignore поставляемый
Просмотреть файл

@ -23,6 +23,8 @@ project.xcworkspace
# Gradle
/build/
/packages/react-native-codegen/android/build/
/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build
/packages/rn-tester/android/app/build/
/packages/rn-tester/android/app/gradle/
/packages/rn-tester/android/app/gradlew

Просмотреть файл

@ -105,20 +105,19 @@ public class CodegenPlugin implements Plugin<Project> {
extension.codegenJavaPackageName,
new File(generatedSrcDir, "java"));
});
// TODO: generate JNI C++ files.
task.commandLine("echo");
} else {
ImmutableList<String> execCommands =
new ImmutableList.Builder<String>()
.add("yarn")
.addAll(ImmutableList.copyOf(extension.nodeExecutableAndArgs))
.add(extension.codegenGenerateNativeModuleSpecsCLI().getAbsolutePath())
.add("android")
.add(generatedSchemaFile.getAbsolutePath())
.add(outputDir.getAbsolutePath())
.build();
task.commandLine(execCommands);
}
ImmutableList<String> execCommands =
new ImmutableList.Builder<String>()
.add("yarn")
.addAll(ImmutableList.copyOf(extension.nodeExecutableAndArgs))
.add(extension.codegenGenerateNativeModuleSpecsCLI().getAbsolutePath())
.add("android")
.add(generatedSchemaFile.getAbsolutePath())
.add(outputDir.getAbsolutePath())
.add(extension.libraryName)
.build();
task.commandLine(execCommands);
});
// 4. Add dependencies & generated sources to the project.

Просмотреть файл

@ -7,7 +7,9 @@
package com.facebook.react.codegen.plugin;
import com.google.common.base.CaseFormat;
import java.io.File;
import java.util.StringTokenizer;
import org.gradle.api.Project;
public class CodegenPluginExtension {
@ -15,12 +17,14 @@ public class CodegenPluginExtension {
public String codegenJavaPackageName = "com.facebook.fbreact.specs.beta";
public boolean enableCodegen = false;
public File jsRootDir;
public String libraryName;
public String[] nodeExecutableAndArgs = {"node"};
public File reactNativeRootDir;
public boolean useJavaGenerator = false;
public CodegenPluginExtension(final Project project) {
this.reactNativeRootDir = new File(project.getRootDir(), "node_modules/react-native");
this.libraryName = projectPathToLibraryName(project.getPath());
}
public File codegenDir() {
@ -34,4 +38,16 @@ public class CodegenPluginExtension {
public File codegenGenerateNativeModuleSpecsCLI() {
return new File(this.reactNativeRootDir, "scripts/generate-native-modules-specs-cli.js");
}
private String projectPathToLibraryName(final String projectPath) {
final StringTokenizer tokenizer = new StringTokenizer(projectPath, ":-_.");
final StringBuilder nameBuilder = new StringBuilder();
while (tokenizer.hasMoreTokens()) {
nameBuilder.append(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, tokenizer.nextToken()));
}
nameBuilder.append("Spec");
return nameBuilder.toString();
}
}

Просмотреть файл

@ -44,6 +44,10 @@ Native::_MODULE_NAME_::SpecJSI::Native::_MODULE_NAME_::SpecJSI(const JavaTurboMo
::_PROPERTIES_MAP_::
}`.trim();
const oneModuleLookupTemplate = ` if (moduleName == "::_MODULE_NAME_::") {
return std::make_shared<Native::_MODULE_NAME_::SpecJSI>(params);
}`;
const template = `
/**
* Copyright (c) Facebook, Inc. and its affiliates.
@ -61,6 +65,10 @@ namespace react {
::_MODULES_::
std::shared_ptr<TurboModule> ::_LIBRARY_NAME_::_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
::_MODULE_LOOKUP_::
}
} // namespace react
} // namespace facebook
`;
@ -323,10 +331,17 @@ module.exports = {
})
.join('\n');
const moduleLookup = Object.keys(nativeModules)
.map(name => {
return oneModuleLookupTemplate.replace(/::_MODULE_NAME_::/g, name);
})
.join('\n');
const fileName = `${moduleSpecName}-generated.cpp`;
const replacedTemplate = template
.replace(/::_MODULES_::/g, modules)
.replace(/::_LIBRARY_NAME_::/g, libraryName)
.replace(/::_MODULE_LOOKUP_::/g, moduleLookup)
.replace(/::_INCLUDE_::/g, `"${moduleSpecName}.h"`);
return new Map([[fileName, replacedTemplate]]);
},

Просмотреть файл

@ -43,6 +43,8 @@ namespace react {
::_MODULES_::
std::shared_ptr<TurboModule> ::_LIBRARY_NAME_::_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
`;
@ -71,8 +73,9 @@ module.exports = {
.join('\n');
const fileName = `${moduleSpecName}.h`;
const replacedTemplate = template.replace(/::_MODULES_::/g, modules);
const replacedTemplate = template
.replace(/::_MODULES_::/g, modules)
.replace(/::_LIBRARY_NAME_::/g, libraryName);
return new Map([[fileName, replacedTemplate]]);
},
};

Просмотреть файл

@ -42,6 +42,12 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboMo
methodMap_[\\"getArrays\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArrays};
}
std::shared_ptr<TurboModule> COMPLEX_OBJECTS_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
if (moduleName == \\"SampleTurboModule\\") {
return std::make_shared<NativeSampleTurboModuleSpecJSI>(params);
}
}
} // namespace react
} // namespace facebook
",
@ -72,6 +78,12 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboMo
}
std::shared_ptr<TurboModule> EMPTY_NATIVE_MODULES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
if (moduleName == \\"SampleTurboModule\\") {
return std::make_shared<NativeSampleTurboModuleSpecJSI>(params);
}
}
} // namespace react
} // namespace facebook
",
@ -107,6 +119,12 @@ NativeAliasTurboModuleSpecJSI::NativeAliasTurboModuleSpecJSI(const JavaTurboModu
methodMap_[\\"cropImage\\"] = MethodMetadata {1, __hostFunction_NativeAliasTurboModuleSpecJSI_cropImage};
}
std::shared_ptr<TurboModule> NATIVE_MODULES_WITH_TYPE_ALIASES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
if (moduleName == \\"AliasTurboModule\\") {
return std::make_shared<NativeAliasTurboModuleSpecJSI>(params);
}
}
} // namespace react
} // namespace facebook
",
@ -190,6 +208,18 @@ NativeExceptionsManagerSpecJSI::NativeExceptionsManagerSpecJSI(const JavaTurboMo
methodMap_[\\"dismissRedbox\\"] = MethodMetadata {0, __hostFunction_NativeExceptionsManagerSpecJSI_dismissRedbox};
}
std::shared_ptr<TurboModule> REAL_MODULE_EXAMPLE_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
if (moduleName == \\"CameraRollManager\\") {
return std::make_shared<NativeCameraRollManagerSpecJSI>(params);
}
if (moduleName == \\"ImagePickerIOS\\") {
return std::make_shared<NativeImagePickerIOSSpecJSI>(params);
}
if (moduleName == \\"ExceptionsManager\\") {
return std::make_shared<NativeExceptionsManagerSpecJSI>(params);
}
}
} // namespace react
} // namespace facebook
",
@ -273,6 +303,12 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboMo
methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise};
}
std::shared_ptr<TurboModule> SIMPLE_NATIVE_MODULES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
if (moduleName == \\"SampleTurboModule\\") {
return std::make_shared<NativeSampleTurboModuleSpecJSI>(params);
}
}
} // namespace react
} // namespace facebook
",
@ -317,6 +353,15 @@ NativeSample2TurboModuleSpecJSI::NativeSample2TurboModuleSpecJSI(const JavaTurbo
methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc};
}
std::shared_ptr<TurboModule> TWO_MODULES_DIFFERENT_FILES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
if (moduleName == \\"SampleTurboModule\\") {
return std::make_shared<NativeSampleTurboModuleSpecJSI>(params);
}
if (moduleName == \\"Sample2TurboModule\\") {
return std::make_shared<NativeSample2TurboModuleSpecJSI>(params);
}
}
} // namespace react
} // namespace facebook
",
@ -359,6 +404,15 @@ NativeSample2TurboModuleSpecJSI::NativeSample2TurboModuleSpecJSI(const JavaTurbo
methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc};
}
std::shared_ptr<TurboModule> TWO_MODULES_SAME_FILE_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
if (moduleName == \\"SampleTurboModule\\") {
return std::make_shared<NativeSampleTurboModuleSpecJSI>(params);
}
if (moduleName == \\"Sample2TurboModule\\") {
return std::make_shared<NativeSample2TurboModuleSpecJSI>(params);
}
}
} // namespace react
} // namespace facebook
",

Просмотреть файл

@ -29,6 +29,8 @@ public:
};
std::shared_ptr<TurboModule> COMPLEX_OBJECTS_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
",
@ -64,6 +66,8 @@ public:
};
std::shared_ptr<TurboModule> EMPTY_NATIVE_MODULES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
",
@ -99,6 +103,8 @@ public:
};
std::shared_ptr<TurboModule> NATIVE_MODULES_WITH_TYPE_ALIASES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
",
@ -150,6 +156,8 @@ public:
};
std::shared_ptr<TurboModule> REAL_MODULE_EXAMPLE_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
",
@ -185,6 +193,8 @@ public:
};
std::shared_ptr<TurboModule> SIMPLE_NATIVE_MODULES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
",
@ -228,6 +238,8 @@ public:
};
std::shared_ptr<TurboModule> TWO_MODULES_DIFFERENT_FILES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
",
@ -271,6 +283,8 @@ public:
};
std::shared_ptr<TurboModule> TWO_MODULES_SAME_FILE_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
",

Просмотреть файл

@ -15,9 +15,8 @@ const mkdirp = require('mkdirp');
const os = require('os');
const path = require('path');
function generateSpec(platform, schemaPath, outputDirectory) {
const libraryName = 'FBReactNativeSpec';
const moduleSpecName = 'FBReactNativeSpec';
function generateSpec(platform, schemaPath, outputDirectory, libraryName) {
const moduleSpecName = libraryName;
const schemaText = fs.readFileSync(schemaPath, 'utf-8');
if (schemaText == null) {
@ -97,7 +96,8 @@ function main() {
const platform = args[0];
const schemaPath = args[1];
const outputDir = args[2];
generateSpec(platform, schemaPath, outputDir);
const libraryName = args[3] || 'FBReactNativeSpec';
generateSpec(platform, schemaPath, outputDir, libraryName);
}
main();