Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/32840Closes#31516
I've cherry-picked the original PR that had merge conficts + updated all
the headers as the one for the TurboModule generators were not handled.
Original Commit Message from acoates
The codegen generates a Facebook copyright notice at the top of the generated files.
While this might make sense on the core files, this codegen will be run on external components too.
The notice also refers to a LICENSE file in the root of this project, which might not be there if this is run on another project.
I did a quick look at some of the codegen that we ship within windows dev tools, and it looks like we normally just have comments
saying the file was codegen'd and so the file shouldn't be manually edited.
Open to suggestions on what the comment header should say.
Changelog:
[General] [Changed] - Do not include Facebook license on users codegen'd code
Reviewed By: ShikaSD
Differential Revision: D33455176
fbshipit-source-id: b247e72efb242e79d99b388c80e4126633e5234d
Summary:
## Context
Inside native ViewConfigs, events are declared using these bubbling/direct EventType maps:
```
{
uiViewClassName: '...',
bubblingEventTypes: {
topFoo: {
registrationName: "onFoo"
}
},
directEventTypes: {},
validAttributes: {
},
}
```
**Pattern:** Note that the top name (i.e: topFoo) is just the registration name (i.e: onFoo) but with "on" replaced with "top".
On Android, registration names and top names don't have to follow this pattern. The top name can be **anything.** See ReactionsDockView:
https://www.internalfb.com/code/fbsource/[c430d46ed69a03a9d9f40cefa335a6d8bb92f8ec]/fbandroid/java/com/facebook/feedback/reactions/ui/overlay/react/ReactionsDockViewManager.java?lines=26-28%2C32-34%2C38
Here, ReactionDismissedEvent.EVENT_NAME is "topDismiss"
https://www.internalfb.com/code/fbsource/[c9f92314a5c46e561a831100dab82164808b05d0]/fbandroid/java/com/facebook/feedback/reactions/ui/overlay/react/ReactionDismissedEvent.java?lines=10-11%2C26
And so to provide you the flexibility to specify a custom topName, the codegen supports a customTopName in the direct/bubbling event types:
```
onDismissWithFeedbackReaction: DirectEventHandler<Event, 'topDismiss'>,
```
This generates the two bubbling event type entries in ReactionsDockView:
```
{
uiViewClassName: '...',
bubblingEventTypes: {
// custom top name
topDismiss: {
registrationName: "onDismissWithFeedbackReaction"
},
// what the top name should actually be
topDismissWithFeedbackReaction: {
registrationName: "onDismissWithFeedbackReaction"
}
},
directEventTypes: {},
validAttributes: {
},
}
```
**The Problem:** The entry created for "topDismissWithFeedbackReaction" is not necessary. This additional entry creates a discrepancy between ReactionsDockView's static ViewConfig and native ViewConfig. Therefore, this diff removes the second unnecessary entry.
Changelog: [Internal]
Reviewed By: JoshuaGross
Differential Revision: D33418730
fbshipit-source-id: 3988ff6906ad1b2e1ef988a19c64d1e042381ab1
Summary:
With SVC enabled for codegenNativeComponent, use `UIManager.hasViewManagerConfig(viewManagerName)` instead of `UIManager.getViewManagerConfig(viewManagerName)` to check for whether the native component is in the app BUCK binary.
This is safe because `global.__fbStaticViewConfig` is gated with MC, and the purpose of SVCs is to stop using `getViewManagerConfig` to get view configs from the Paper view managers. Currently no QEs have SVCs enabled.
Changelog:
[Fabric][JS] For codegenNativeComponent, with SVC enabled, use UIManager hasViewManagerConfig instead of getViewManagerConfig
Reviewed By: RSNara
Differential Revision: D33511365
fbshipit-source-id: 58c7020903137e2b5c80ef34a956be04de51628b
Summary:
For every direct and bubbling event, RCTComponentData (iOS-only) creates a {eventName}: true entry in the component's ViewConfig validAttributes. This entry is unnecessary, and creates a discrepancy between ViewConfigs on iOS vs Android.
This diff removes this entry for all events to:
1. Reduce bloat in native ViewConfigs
2. Create consistency betweeen Android and iOS.
Changelog: [Internal]
Reviewed By: yungsters
Differential Revision: D33303950
fbshipit-source-id: 870c8a2a6d41156ac89bd8554eb09f292bb6108e
Summary:
Renaming the `better` utilities to `butter`:
- to prevent claims that this library is superior to others - it really depends on use cases
- to indicate ease of use throughout the codebase, easily spread like butter
Changelog: [C++][Changed] Renaming C++ better util to butter, used by Fabric internals
Reviewed By: JoshuaGross
Differential Revision: D33242764
fbshipit-source-id: 26dc95d9597c61ce8e66708e44ed545e0fc5cff5
Summary:
Tests for Native Modules. Fixtures, Failures and the e2e tests were copied from the flow parser, modified for TypeScript and then the snapshots were diff'ed to ensure the parsers generated the same schema given the same (in spirit, different in syntax) input.
Changelog:
[General][Add] - Tests for TypeScript support for Native Module Codegen spec parsing
Reviewed By: RSNara
Differential Revision: D33081127
fbshipit-source-id: 3d7270dddd568090ec93d475a08a6a6011dad63c
Summary:
Tests for Native Components. Fixtures, Failures and the e2e tests were copied from the flow parser, modified for TypeScript and then the snapshots were diff'ed to ensure the parsers generated the same schema given the same (in spirit, different in syntax) input.
Changelog:
[General][Add] - Tests for TypeScript support for Native Component Codegen spec parsing
Reviewed By: RSNara
Differential Revision: D33080789
fbshipit-source-id: ae71d384f6d93da6b89eeb179c4ba7ebcd6ae03d
Summary:
These files are directly copied from the flow parser to aid in reviewing the next two Diffs: D33080789 and D33081127.
The only things that were changed during the copy are the import/require paths to ensure this diff could ship independently. (For this diff, these tests will still test the flow parser instead of importing the typescript parser).
Changelog:
[Internal][Add] - Copy Flow parser tests to aid in Diff review
Reviewed By: RSNara
Differential Revision: D33136296
fbshipit-source-id: 007e18618c9eba13728d19e4e342fbe9642adacc
Summary:
This adds the main entry point for the TypeScript parser as well as adds the logic to use the new parser if the spec file's extension is `.ts`
`js/react-native-github/packages/react-native-codegen/src/parsers/typescript/index.js` is mostly a direct copy from the flow parser.
Changelog:
[General][Add] - Choose Flow or WIP TypeScript Codegen parser based on spec's file extension
Reviewed By: RSNara
Differential Revision: D33081296
fbshipit-source-id: 267823685e6723e3c1f19752bbbe692e895c075b
Summary:
Similar to D33080623, this is the logic for parsing Native Modules and the files were copied from the flow parser and updated for TypeScript. The logic and code path is almost identical to the flow parser.
Also, like D33080623, while there is considerable duplication to the flow parser, I decided there are enough subtle differences to warrant keeping this logic separate.
Changelog:
[General][Add] - Add WIP TypeScript support for Native Module Codegen spec parsing
Reviewed By: RSNara
Differential Revision: D33081035
fbshipit-source-id: 5a196e4693df73c0fb88abafe2b4e6be032ea7ed
Summary:
These files are directly copied from the flow parser to aid in reviewing the next Diff, D33081035
Changelog:
[Internal][Add] - Copy Flow parser module logic to aid in Diff review
Reviewed By: RSNara
Differential Revision: D33134982
fbshipit-source-id: 9afea2ce15404338fd2c920a8b7eafe980f18688
Summary:
This is the logic for parsing Native Components. The files were copied from the flow parser and updated for TypeScript specific types and differences in the shape of the AST. The logic and code path is almost identical to the flow parser.
While there is considerable duplication to the flow parser, I decided there are enough subtle differences to warrant keeping this logic separate.
Changelog:
[General][Add] - Add WIP TypeScript support for Native Component Codegen spec parsing
Reviewed By: RSNara
Differential Revision: D33080623
fbshipit-source-id: a68c8d4c4570e65a88a97dcea3cd18a6976c53c7
Summary:
These files are directly copied from the flow parser to aid in reviewing the next Diff, D33080623
Changelog:
[Internal][Add] - Copy Flow parser component logic to aid in Diff review
Reviewed By: RSNara
Differential Revision: D33130222
fbshipit-source-id: ba7233b17d698793559da8b81bb7e1a78654e614
Summary:
These are utility functions that the TypeScript parser uses and are copied from and follows the same logic as the flow parser with some TypeScript specific changes. Also added dependency of `babel/parser` as the parsing engine we're using for TypeScript.
Changelog:
[General][Add] - Add foundation for WIP TypeScript parser for Codegen
Reviewed By: RSNara
Differential Revision: D33080527
fbshipit-source-id: d4bd515af549a41f07a2e3ee1a16b5ed678180b2
Summary:
This is a direct copy of the following files from the flow parser:
```
react-native-codegen/src/parsers/flow/errors.js
react-native-codegen/src/parsers/flow/utils.js
```
Changelog:
[Internal][Added] - Copy flow parser foundation files to aid in diff review
Reviewed By: RSNara
Differential Revision: D33137685
fbshipit-source-id: 1345c8bb0785c90b2bd64d4e6e2447f3fdb0ae6b
Summary:
Currently the codegen does not include component with field `interfaceOnly` set to `true` in the `ThirdPartyFabricComponentsProvider`.
These components need to be added to this file, so that non-core components can be used in fabric.
## Changelog
[General [Fixed] - Fixes GenerateThirdPartyFabricComponentsProvider
Pull Request resolved: https://github.com/facebook/react-native/pull/32779
Test Plan:
Run codegen with component outside of core on iOS.
Check if components with and without `interfaceOnly` are added to `RCTThirdPartyFabricComponentsProvider`
Reviewed By: cortinico
Differential Revision: D33235363
Pulled By: ShikaSD
fbshipit-source-id: e7224d2123e4da0da912fe677dae32d3aaea2ec8
Summary:
This diff stack enables codegen to parse TypeScript spec files and generate an identical schema to our current Flow parser.
This first diff is a small cleanup of our current flow parser.
Changelog:
[General][Fixed] - Fix typo in error string and improve consistency in Codegen's flow parser tests
Reviewed By: sota000
Differential Revision: D33080423
fbshipit-source-id: 7bf817761a7704d807a0b809c9f2270354b5c6fa
Summary:
So I was adding a new HTTPCookie prop to our WebView native component and found that my build was [failing](https://www.internalfb.com/diff/D32602297?dst_version_fbid=338931330931416) due to "redefinition of `value`". Looks like we use the name of the prop as a variable name during codegen, and this can conflict with some other hardcoded variable names. Rather than try and come up with a better prop name, I figured we can just append some string to our codegen name to reduce the chance for conflicts.
Changelog:
[Internal][Changed] - Change codegen variable naming to prevent conflicts to prop names
Reviewed By: JoshuaGross
Differential Revision: D32967807
fbshipit-source-id: 1b3631ec783b229eddfd3c801ffbb397910fc882
Summary:
The Codegen is generating a broken output if using the default library name: `Packages<GradleModuleName>Spec`.
This diff is fixing the codegenerator to don't call the `.lowerCase` on the library name when generating the Makefile.
Changelog:
[Android] [Fixed] - Do not .lowerCase the library name when codegenerating TurboModule Specs
Reviewed By: ShikaSD
Differential Revision: D32597578
fbshipit-source-id: dee729a44134d7b3878074507191bb2a1c200608
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:
Currently, we don't have a way to extend RCTFabricComponentsPlugins in OSS. This diff adds a codegen to generate ThirdpartyFabricComponentsProviderwhich will be used to extend RCTFabricComponentsPlugins.
It works almost exactly the same as RCTFabricComponentsPlugins, and in the future we might want to consider merging them together.
Changelog: [internal]
Reviewed By: hramos
Differential Revision: D32128760
fbshipit-source-id: b4f3a082f94c3053251cc6a0323c488f649deaa9
Summary:
When I upgraded React Native to Prettier v2.x, I removed `format` from a few files to reduce the number of changes.
This is a follow-up to bring back `format` and fix any remaining issues.
Changelog:
[Internal]
Reviewed By: zertosh
Differential Revision: D32287259
fbshipit-source-id: 37ea6d2c973b1db5d37c46d73675bdf436fb9a9d
Summary:
We are in the middle of a Prettier upgrade and some of the files which disagree between Prettier v1.x and v2.x are now being flagged by `eslint-plugin-prettier` as lint errors.
The correct fix here is probably to update `eslint-config-prettier` and `eslint-plugin-prettier`, but I am landing this first to unbreak CI.
Reviewed By: mendoncakeegan
Differential Revision: D32129458
fbshipit-source-id: a5206a5ef58f1d7614f9459c99b9e39109be6de9
Summary:
**Motivation:** Readability. It was hard to tell how componentName, paperComponentName, and paperComponentNameDepreacted produced the NativeComponentRegistry.get call.
Changelog: [Internal]
Reviewed By: philIip
Differential Revision: D32108276
fbshipit-source-id: ea7c9fe4dc50cdd6fec94b5cd25f7bbcfb451ef6
Summary:
## Rationale
**Disclaimer**: This is an incremental step towards more maintainable/readable react-native-codegen generators. In the future, we may want to replace these templates/string concat logic with *something better*. But until we decide what that *something better* is, let's at least get rid of all this gross string find/replace.
Benefits of using Function templates over String.prototype.replace.
- **Self-documenting**: Template Functions enumerate/describe their exact data dependencies in their signature. You no longer have to read the template implementation to see what data you need to pass into the template.
- **Improved Readability**: JavaScript syntax highlighting makes it really easy to see where/how the data is inserted into the templates. Also template variables used be prefixed/suffixed with ::, which made things really confusing in C++ code (e.g: wtf is `::_CLASSNAME_::EventEmitter::::_EVENT_NAME_::`?).
- **Simpler Interpolation**: Don't have to worry about .replaceAll vs .replace, or calling these replace functions with regexes or strings.
- **Template Type-safety**: Ensure that the correct data types are passed to the component templates (e.g: flow will complain if you accidentally pass null/undefined when a template expects a string).
- **Template Type-safety**: Ensure that we don't pass in extra data to templates (this diff catches/fixes instances of this error). Ensure that we don't forget to pass in data to the template.
- etc.
After this diff, both our Component and NativeModule generators will be using template functions. This string find/replace exists no more in react-native-codegen.
This is also a very surface-level change. I made no efforts to simplify these templates. Let's take a look at that later, as necessary.
Changelog: [Internal]
Reviewed By: yungsters
Differential Revision: D32021441
fbshipit-source-id: f8f27069bcbf9d66dcafb7d1411da1f938eb6dcd
Summary:
While working updating the codeden Makefile template for Android, I've removed
the `libreact_debug` and `libreact_render_debug` dependencies as they were unused in a
simple turbomodule. Turns out that `:ReactAndroid` is depending on having those dependencies.
Moving the build file to use AGP APIs, triggers this scenario and is making `ReactAndroid`
failing to build (see the build status for https://github.com/facebook/react-native/pull/32443).
I'm updating the codegen Makefile template to reintrodce the two libraries + I've update the prebuilt
makefile (used in the playbook) to include `react_debug` prebuilts as they were missing.
Changelog:
[Internal] [Changed] - Re-add libreact_debug to codegen makefile and add prebuilts for them
Reviewed By: ShikaSD
Differential Revision: D31900675
fbshipit-source-id: ff188c0498a0dca4a951a548a580ca8dd0674782
Summary:
Adds the `glob` type definition via `flow-typed` so that the `combine-js-to-schema-cli.js` script does not need a Flow suppression.
Changelog:
[Internal]
Reviewed By: kacieb
Differential Revision: D31800809
fbshipit-source-id: 3e01a096d2153639a619a7152bd06332df57f06b
Summary:
This diff updates the Makefile generated by `react-native-codegen`
to include the correct list of modules. Specifically I've removed some modules that are unused
like `libreact_debug` and added others that are necessary for the build to compile correctly
such as `libfbjni`.
Plus I've bumped the C++ version to 17 as we had a mixture of 14 and 17 across the codebase.
Changelog:
[Internal] [Changed] - Update codegen template to include correct native modules and C++17
Reviewed By: mdvacca
Differential Revision: D31754427
fbshipit-source-id: 8490fa5c5ad298689b564f760c3fc65550c94547
Summary:
I had to make this change when enabling Fabric in OSS. Without the full path, it can't find the modules like processColor within node_modules.
Changelog: Internal
Reviewed By: motiz88
Differential Revision: D31300424
fbshipit-source-id: 59b82470ec1ce63b63704931786e22b98f4bf046
Summary:
Changelog: [Internal]
Some environments that use codegen don't have Haste enabled, breaking the `require('NativeComponentRegistry')` call in generated view configs. Here we change it to reference an explicit path relative to `react-native`.
Reviewed By: JoshuaGross
Differential Revision: D31166063
fbshipit-source-id: cebc23d0d95b5cde76d0f8473eabc03ca82a862e
Summary:
If I understand the code correctly, component.extendsProps is expected to have more than 1 entry. I encounter a bug where it was an empty and produced an broken Props.h file while testing out in OSS.
```
// Example of the broken file.
class RNTMyNativeViewProps final : {
public:
```
In this diff, it makes it clear that the function has failed so that the codegen fails when the input is wrong.
There is probably an upstream problem that we should warn about, but this diff is just to make sure this method fails loudly.
Changelog: [Internal]
Reviewed By: hramos
Differential Revision: D30847173
fbshipit-source-id: 34c894f0a7bb81e132b6ed44f51d0f92ed9a5a20
Summary:
Adding an error message when codegen doesn't recognize any modules to help users understand what's going on.
Changelog: [Internal]
Reviewed By: RSNara
Differential Revision: D30624535
fbshipit-source-id: 781f1f874a5b0c16a05191186b81c2d3892da95b
Summary:
Ship libjsi as a standalone dynamic library. This prevents problems
with exception handling caused by duplicate typeinfo across multiple
shared libs, and reduces bundle size by removing duplicate copies of
JSI.
Changelog: [Internal]
Reviewed By: fkgozali
Differential Revision: D30599215
fbshipit-source-id: abad1398342a5328daa825f3f684e0067cad7a96
Summary:
See previous diffs for context. This updates all of the relevant props structs.
Changelog: [Internal]
Reviewed By: mdvacca
Differential Revision: D29855426
fbshipit-source-id: 30177c3380ef82ecf8f2a4321f128cfbe8a576e0
Summary:
String type seems to be already supported by codegen, but it was not included in the list for command methods.
Changelog: [Internal]
Reviewed By: JoshuaGross
Differential Revision: D29306740
fbshipit-source-id: 44b267c09f471dc601759ed2f7211a9e0fc1bb90
Summary:
This pre-suppresses the 154 error diff ahead of its release, since it is large.
Changelog: [Internal]
Reviewed By: samwgoldman
Differential Revision: D29065246
fbshipit-source-id: f418041305a46df410dcbe3d9a4db81a61ac7014
Summary:
This pre-suppresses the 153 error diff ahead of its release, since it is large.
Changelog: [Internal]
Reviewed By: mroch
Differential Revision: D28754374
fbshipit-source-id: 1806f53bc7d804644d434583a2dcd6da63d00328
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/31543
Changelog:
[iOS][Added] - Description
When compiling iOS apps with flag `-Wnullability-completeness` (like Lightspeed app and soon Instagram), Objective-C headers are required to either have full *explicit* nullability annotations on all members of its public API, or none at all; partially annotated headers will fail to build that module.
RN native modules are currently generated with *partial* annotations. This works today because most apps are not compiled with `-Wnullability-completeness` turned on. But when we flip the switch for Instagram, the app doesn't build due to importing these RN partially annotated modules.
JavsScript Flow types are implied nonnull, and the current RN codegen translates Flow's [maybe/optional](https://flow.org/en/docs/types/maybe/) type to Obj-C `_Nullable` annotation, and everything else without an explicit Obj-C annotation. However this creates a mismatch with the Obj-C type system, where the implied default is *unannotated*, which is handled differently from nonnull when built with the nullability compiler flags.
There is a simple Obj-C macro that automatically adds *explicit nonnull* annotations to all members in a header: `NS_ASSUME_NONNULL_BEGIN` / `NS_ASSUME_NONNULL_END`. If we add this to *all* RN-generated headers, however, we run into issues:
1) We may erroneously assume any previously-unannotated header was meant to be nonnull and cause future bugs
2) Another compiler flag (`-Wnullable-to-nonnull-conversion`) statically analyzes Obj-C implementation code to prevent us from ever passing null to one of these headers. Much existing Obj-C code will break here, and it's ambiguous if these are true or false positives because of the first point.
Instead, in this diff we add a new BUCK flag `ios_assume_nonnull` to let module authors opt into automatic nonnull for unannotated members so that Obj-C headers are generated correctly in alignment with Flow's type system. We can migrate all libraries individually as needed and eventually make this the RN native codegen default.
Reviewed By: RSNara
Differential Revision: D28396446
fbshipit-source-id: ad3a3a97ab19183df4ef504b1c3140596c8f69ca
Summary:
This should ensure that nothing is stripped at compile-time.
Changelog: [Internal]
Reviewed By: mdvacca
Differential Revision: D26094738
fbshipit-source-id: 8dd62c289deafdcceb3de4b09c12132aaceafa94
Summary:
Changelog: [Internal]
Adds react_debug dependency in Android.mk where it was missing
Reviewed By: mdvacca
Differential Revision: D26617400
fbshipit-source-id: 5ac799269b106eadd881d30490ac34bd2134a9b7
Summary:
Building ReactAndroid from source on Windows has recently hit the limitation of maximum path lengths.
At build time, during the `:ReactAndroid:buildReactNdkLib` task, the linker tries to access several of the intermediate binaries located deep in the tmp folder hierarchy, eg.
```
D:\r\ReactAndroid\build\tmp\buildReactNdkLib/local/armeabi-v7a/objs/react_render_components_progressbar/D_/r/ReactAndroid/__/ReactCommon/react/renderer/components/progressbar/android/react/renderer/components/progressbar/AndroidProgressBarMeasurementsManager.o
```
**Suggested fix:** for modules such as `react_render_components_progressbar` and `react_render_components_picker`, rename them to `rrc_progressbar` etc.
**NOTE**: this assumes that the fix from https://github.com/facebook/react-native/issues/30535 is in place. This regression happened while https://github.com/facebook/react-native/issues/30535 has been pending checkin.
**Other mitigations I've tried:**
- setting [`LOCAL_SHORT_COMMANDS`](https://developer.android.com/ndk/guides/android_mk#local_short_commands) for the problematic modules or `APP_SHORT_COMMANDS` for the root project. Turns out those commands don't work on the NDK version RN requires, but even after manually applying a [patch ](https://android-review.googlesource.com/c/platform/ndk/+/1126440) to my local copy of the NDK, these flags had no effect.
- moving the repo directory higher in the file system tree, and using short directory names `D:\r\...` was not enough
- creating virtual drive letters for specific long paths with the [`sust`](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/subst#examples) command is not workable, since they depend on the source folder structure, and get partly generated by the build system, which I can't plug into
- just enabling long path support on Windows is not enough, since the compiler toolchain doesn't support them.
## Changelog
<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://github.com/facebook/react-native/wiki/Changelog
-->
[Android] [Fixed] - Fix source build on Windows machines vol. 2
Pull Request resolved: https://github.com/facebook/react-native/pull/30776
Test Plan:
Run `.\gradlew installArchives`
Before:

Now:

Differential Revision: D26194286
Pulled By: mdvacca
fbshipit-source-id: 778b5a0515148e2ace19e7902f74301831ebed94
Summary:
NativeModule getConstants() methods on Java might not be used within Java. So, they can be stripped by proguard. This diff adds the DoNotStrip annotation to the getConstants() method.
Changelog: [Internal]
Reviewed By: keoskate
Differential Revision: D26265874
fbshipit-source-id: b405ee32406e829212e5c9641750a6b5795899c3
Summary:
To ensure these Pojos don't get dead code eliminated, this diff adds a DoNotStrip annotation to each Props pojo object.
Changelog: [Internal]
Reviewed By: mdvacca
Differential Revision: D26041103
fbshipit-source-id: 02031f39f5fc5ef1bb9f11b729e68437bfe95452