Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/46845
Previously, the parser was throwing away the values of a string union when storing it in the schema. It would only store the union as
```
{
type: 'UnionTypeAnnotation',
memberType: 'StringTypeAnnotation'
}
```
We now track the string literals through the parser and store them in the schema:
```
{
type: 'StringLiteralUnionTypeAnnotation',
types: [
{
type: 'StringLiteralTypeAnnotation'
value: 'light'
},
{
type: 'StringLiteralTypeAnnotation'
value: 'dark'
},
],
}
```
We aren't changing the generators, those still just output "string". They could eventually be made smarter.
The value of this is that the compat checker can now error when the union changes.
Changelog: [Internal]
Reviewed By: yungsters
Differential Revision: D63917685
fbshipit-source-id: 34a10e1f1910d2935837a3659f66049fd4473134
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
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/46221
Previously the schema special cased unparseable elementType with elementType just being undefined. This causes issues for logic that requires recursively matching types. Instead of being implicit, this makes them explicitly an AnyTypeAnnotation
Changelog: [Internal]
Reviewed By: makovkastar
Differential Revision: D61825742
fbshipit-source-id: 47bf70d32d21647896d8f5319087378cc8ac8d4f
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/42122
This diff introduces the `TypeUtils` directory where we can put platform-specific, context-independent type transformations.
Changelog: [Internal]
Reviewed By: cipolleschi
Differential Revision: D52291837
fbshipit-source-id: 561b9c494aab5bfee3b3c668d3346bbd320e5266
Summary:
This PR is a task from https://github.com/facebook/react-native/issues/34872
_Extract the modules/utils.js from the flow and typescript folders in a shared parsers-commons.js file. Then, have the two parsers use the same wrapModuleSchema function for modules._
(`wrapModuleSchema` is a copy-paste mistake, in this case it is `wrapNullable` and `unwrapNullable`)
## Changelog
<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->
[Internal] [Changed] - Extracts Codegen's modules/utils.js files from the flow and typescript folders in parsers-commons
Pull Request resolved: https://github.com/facebook/react-native/pull/34898
Test Plan:
I ran `yarn jest react-native-codegen`:
<img width="775" alt="Capture d’écran 2022-10-07 à 21 29 48" src="https://user-images.githubusercontent.com/17070498/194639515-a446c2cf-daf3-43a1-9833-cd546ca5865e.png">
Reviewed By: cipolleschi
Differential Revision: D40193740
Pulled By: cipolleschi
fbshipit-source-id: 02cbacc215fe5dd9bdd0839d8796587ab2821906
Summary:
This diff runs the codemod to add type annotations to function parameters in preparation for Flow's local type inference (LTI) project. I ran the codemod over xplat/js and reverted any files that had flow errors in them. See the list of commands run to see the regeneration of various files.
Changelog:
[Internal][Changed] - Added type annotations
Reviewed By: yungsters
Differential Revision: D32075270
fbshipit-source-id: 6a9cd85aab120b4d9e690bac142a415525dbf298
Summary:
## What This Does
- **Phase 1:** Given a component, convert its props (and all its ObjectTypeAnnotations) into this Pojo data structure under some namespace. This is a recursive operation.
- **Phase 2:** Loop over each Pojo data structure, and serialize it to Java class.
So...
- Each Component has its own namespace (i.e: its hasteModuleName) for Java Pojo objects.
- Each Component generates 1 Pojo object, for its props.
- Each Component generates 1 Pojo object for every ObjectTypeAnnotation in its props.
## Decisions
By design, [JNI can read/write to private properties on Java objects](https://stackoverflow.com/a/12208643). So, each Pojo, which represents an ObjectTypeAnnotation, contains only a private member variable for each of its properties, and a getter to retrieve the data from each of its private members.
## Todos
- Improved type-safety:
- ReservedTypeAnnotation (e.g: PointPrimitive). These currently map to ReadableMap.
- String enums, and Int enums don't actually generate Java enums.
- Verify if there are any compilation issues by wiring this up to the Codegen buck infra.
- To actually use the Pojos, we'll need C++/Jni codegen to transform C++ props into these Pojos. Building this out will give a more accurate assessment of the app-size cost of Pojos. However, we can do that if we deem that the app-size increase from adding just the Pojo classes is negligible enough to **not** rule out this entire approach.
- ~~Add some annotations to prevent these Pojo classes from being stripped at compile-time.~~ D26041103
Changelog: [Internal]
Reviewed By: mdvacca
Differential Revision: D26038189
fbshipit-source-id: c137c4ca6b043ee76adb354105aff6e0f270df86
Summary:
## Problem
Suppose we have this NativeModule spec, that uses Object literals that contain a property called "id":
```
export interface Spec extends TurboModule {
// Exported methods.
+getConstants: () => {|
id: string,
|};
+getObject: (arg: {id: Object}) => Object;
}
```
For both object literals, we'll generate C++ structs, backed by NSDictionaries. The method in each struct will be named "id_" to avoid a name clash with ObjC's `id` identifier. However, calling that id_ method should still access the "id" property in the corresponding NSDictionary.
## Expected Output
```
inline id<NSObject> JS::NativeSampleTurboModule::SpecGetObjectArg::id_() const
{
id const p = _v[@"id"];
return p;
}
inline JS::NativeSampleTurboModule::Constants::Builder::Builder(const Input i) : _factory(^{
NSMutableDictionary *d = [NSMutableDictionary new];
auto id_ = i.id_.get();
d[@"id"] = id_;
return d;
}) {}
```
## Actual Output
```
inline id<NSObject> JS::NativeSampleTurboModule::SpecGetObjectArg::id_() const
{
id const p = _v[@"id_"]; // <-- HERE!
return p;
}
inline JS::NativeSampleTurboModule::Constants::Builder::Builder(const Input i) : _factory(^{
NSMutableDictionary *d = [NSMutableDictionary new];
auto id_ = i.id_.get();
d[@"id_"] = id_; // <-- HERE!
return d;
}) {}
```
NOTE: This code was generated by running `jf get --version 119805822 && buck build //xplat/js:FBReactNativeSpec_Sample-flow-types-ios --show-output`
This diff fixes this mistake.
Changelog: [Internal]
Reviewed By: fkgozali
Differential Revision: D25907493
fbshipit-source-id: cb37cbf49db4f871b3f4046f7397a7b1b7df0357
Summary:
## Changes
{| ... |} -> { ... }
**Motivation:** In Flow, object literals are exact by default. So, there's no need for the pipes. Also: Now, the syntax for object literals is consistent across react-native-codegen.
Changelog: [Internal]
Reviewed By: hramos
Differential Revision: D24774771
fbshipit-source-id: 24ceb6f5876122aa8ad9e08c7e903215864ad6f5
Summary:
Reserved type annotations can appear in three different contexts: commands, props, and NativeModules. For now, commands and NativeModules share the same reserved type annotations. In the future, we may want to merge these reserved type annotations with the props reserved type annotations.
**Motivation:** The meaning of FunctionValue in FunctionValueTypeAnnotation isn't clear - in fact, it's downright confusing. Therefore, this diff renames this Flow type to ReservedTypeAnnotation, which I believe sufficiently captures the intent of the type annotation.
Changelog: [Internal]
Reviewed By: yungsters
Differential Revision: D24701322
fbshipit-source-id: bde0273b4a89c9e7175c60ed3468ed870b320044
Summary:
In our Codegen generators, we were using `codegenModuleName` to refer to the name of the spec file. Calling this `hasteModuleName` makes it more clear what this name refers to (i.e: the name of the spec file). This diff performs that rename.
Changelog: [Internal]
Reviewed By: fkgozali
Differential Revision: D24386282
fbshipit-source-id: fe2beda9a0abf63a5cf88fa0664f83416c9f1aa2
Summary:
NOTE: Flow and Jest won't pass on this diff. Sandcastle, should, however, be green on D24236405 (i.e: the tip of this stack).
## Changes
1. NativeModule generators now use the new RN Codegen NativeModule schema.
2. Tangential: We're no longer removing the `Native` prefix from the NativeModule filename, assuming that that's the module name (problem: wrong), and prefixing again with Native (problem: redundant), when we're generating code. Instead, like the internal codegen, we simply pass the filename to the Codegen output. Our linters enforce that all NativeModule specs are contained with files that start off with `Native`.
3. `GenerateModuleCpp` was fixed to use the actual module name as opposed to the spec name. I added a comment inline.
Changelog: [Internal]
(Note: this ignores all push blocking failures!)
Reviewed By: PeteTheHeat
Differential Revision: D24236405
fbshipit-source-id: ccd6b5674d252c350be0ec8a86e7ca5f2f614778
Summary:
Remove extraneous newlines before and after structs, before copyright headers, and other locations.
Changelog: [Internal]
Reviewed By: fkgozali
Differential Revision: D24117137
fbshipit-source-id: 194996019b4cadef9239a78334f31c0bc89e3901
Summary:
## Misc. Improvements
* We now have 95%+ flow coverage in all generator files. Henceforth, we can make changes to these files with more confidence, and trust flow to catch more errors. This should also improve the DevX of working on these files.
* Better templates: Instead of doing string replace with RegExps, we instead use functions and leverage JS template literals to generate our code. A few benefits: (1) data dependencies of templates are clearly visible, and statically checked by flow, (2) the templates are more readable in VSCode.
* Merged the GenerateModuleHObjCpp.js and GenerateModuleMm.js generators. They can share a lot of logic, so it's not a good idea to keep them separate.
* The ObjC++ module generator no longer generates “dead” structs (i.e structs that aren’t used by type-safety infra). In fact, it explicitly only supports the types in our Wiki. (I know this wasn’t the case with the legacy codegen, because we were generating native code for enums in the legacy codegen). This is a mixed bag. The test to verify correctness will be more difficult to write. However, keeping structs in the codegen needlessly complicates the parsers + generators, and creates technical debt for us to clean up later.
## Abstractions
- **StructCollector:** As we serialize NativeModule methods, when we detect an ObjectTypeAnnotation in the return type of `getConstants()` or inside a method param, we must create a Struct JS object for it. When we detect a type-alias (also in the same locations), we must look up that type-alias and create a Struct from its RHS. A Struct is basically an ObjectTypeAnnotation with a context (i.e: used in getConstants() vs as a method param), that cannot contain other ObjectTypeAnnotations.
- **serializeMethod.js** Given a NativeModule method type annotation, output the protocol method, JS return type, selector, a record of which params were structs, and which structs. Basically, this is all the information necessary to generate the declaration and implementation codegen for a partiular NativeModule method.
- **serializeStruct/*.js**: After creating all these Structs, we need to loop over all of them, and tranform them into ObjC++ code.
- **serializeStruct.js**: Depending on the struct context, calls either `serializeRegularStruct.js` or `serializeConstantsStruct.js`. Both of these files have the same layout/abstractions. They look very similar.
- **serializeModule.js:** Outputs RCTCxxConvert categories for transforming `NSDictionary *` into C++ structs. Outputs ObjCTurboModule subclass.
## Algorithm
```
for spec in NativeModuleSpecs
structCollector = new StructCollector
resolveAlias = (aliasName) => nullthrows(spec.aliases[aliasName])
methodDatas = []
for method in methods(spec)
methodData.push(serializeMethod(method, structCollector, resolveAlias))
end
structs = structCollector.getStructs()
output generateImplCodegen(methodDatas, structs)
output generateHeaderCodegen(methodDatas, structs)
end
```
Changelog: [Internal]
Reviewed By: hramos
Differential Revision: D23633940
fbshipit-source-id: 7c29f458b65434f4865ef1993061b0f0dc7d04ce