Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(#38): make module TurboModule-compatible #59

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 17 additions & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@ buildscript {
}
}

def isNewArchitectureEnabled() {
return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
}

apply plugin: 'com.android.library'
if (isNewArchitectureEnabled()) {
apply plugin: "com.facebook.react"
}

def safeExtGet(prop, fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
Expand All @@ -32,12 +39,22 @@ android {
defaultConfig {
minSdkVersion safeExtGet('minSdkVersion', 16)
targetSdkVersion safeExtGet('targetSdkVersion', 30)
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
versionCode 1
versionName "1.0"
}
lintOptions {
abortOnError false
}
sourceSets {
main {
if (isNewArchitectureEnabled()) {
java.srcDirs += ['src/newarch/java', "${project.buildDir}/generated/source/codegen/java"]
} else {
java.srcDirs += ['src/oldarch/java']
}
}
}
}

repositories {
Expand Down
21 changes: 4 additions & 17 deletions android/src/main/java/org/linusu/RNGetRandomValuesModule.java
Original file line number Diff line number Diff line change
@@ -1,32 +1,19 @@
package org.linusu;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import android.util.Base64;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;

public class RNGetRandomValuesModule extends ReactContextBaseJavaModule {

private final ReactApplicationContext reactContext;
import java.security.SecureRandom;

public class RNGetRandomValuesModule extends NativeRNGetRandomValuesSpec {
public RNGetRandomValuesModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
}

@Override
public String getName() {
return "RNGetRandomValues";
}

@ReactMethod(isBlockingSynchronousMethod = true)
public String getRandomBase64(int byteLength) throws NoSuchAlgorithmException {
byte[] data = new byte[byteLength];
public String getRandomBase64(double byteLength) {
byte[] data = new byte[(int)byteLength];
SecureRandom random = new SecureRandom();

random.nextBytes(data);
Expand Down
48 changes: 32 additions & 16 deletions android/src/main/java/org/linusu/RNGetRandomValuesPackage.java
Original file line number Diff line number Diff line change
@@ -1,28 +1,44 @@
package org.linusu;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.facebook.react.ReactPackage;
import com.facebook.react.TurboReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.module.model.ReactModuleInfo;
import com.facebook.react.module.model.ReactModuleInfoProvider;

public class RNGetRandomValuesPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Arrays.<NativeModule>asList(new RNGetRandomValuesModule(reactContext));
}
import java.util.HashMap;
import java.util.Map;

// Deprecated from RN 0.47
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
public class RNGetRandomValuesPackage extends TurboReactPackage {
@Nullable
@Override
public NativeModule getModule(@NonNull String name, @NonNull ReactApplicationContext reactContext) {
if (name.equals(RNGetRandomValuesModule.NAME)) {
return new RNGetRandomValuesModule(reactContext);
}
return null;
}

@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
public ReactModuleInfoProvider getReactModuleInfoProvider() {
return () -> {
boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
moduleInfos.put(
RNGetRandomValuesModule.NAME,
new ReactModuleInfo(
RNGetRandomValuesModule.NAME,
RNGetRandomValuesModule.NAME,
false, // canOverrideExistingModule
false, // needsEagerInit
false, // hasConstants
false, // isCxxModule
isTurboModule // isTurboModule
));
return moduleInfos;
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.linusu;

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 NativeRNGetRandomValuesSpec extends ReactContextBaseJavaModule implements TurboModule {
public static final String NAME = "RNGetRandomValues";

public NativeRNGetRandomValuesSpec(ReactApplicationContext reactContext) {
super(reactContext);
}

@Override
public @Nonnull String getName() {
return NAME;
}

@ReactMethod(isBlockingSynchronousMethod = true)
@DoNotStrip
public abstract String getRandomBase64(double byteLength);
}
6 changes: 4 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const base64Decode = require('fast-base64-decode')
const { NativeModules } = require('react-native')

const NativeRNGetRandomValues = require('./specs/NativeRNGetRandomValues').default

class TypeMismatchError extends Error {}
class QuotaExceededError extends Error {}

Expand All @@ -24,8 +26,8 @@ function insecureRandomValues (array) {
* @returns {string}
*/
function getRandomBase64 (byteLength) {
if (NativeModules.RNGetRandomValues) {
return NativeModules.RNGetRandomValues.getRandomBase64(byteLength)
if (NativeRNGetRandomValues) {
return NativeRNGetRandomValues.getRandomBase64(byteLength)
} else if (NativeModules.ExpoRandom) {
// Expo SDK 41-44
return NativeModules.ExpoRandom.getRandomBase64String(byteLength)
Expand Down
2 changes: 1 addition & 1 deletion ios/RNGetRandomValues.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#import <React/RCTBridgeModule.h>

@interface RNGetRandomValues : NSObject <RCTBridgeModule>
-(NSString*)getRandomBase64:(NSUInteger)byteLength;

@end
20 changes: 0 additions & 20 deletions ios/RNGetRandomValues.m

This file was deleted.

29 changes: 29 additions & 0 deletions ios/RNGetRandomValues.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#import "RNGetRandomValues.h"

#if RCT_NEW_ARCH_ENABLED
#import "RNGetRandomValuesSpec.h"

@interface RNGetRandomValues () <NativeRNGetRandomValuesSpec>
@end
#endif

@implementation RNGetRandomValues

RCT_EXPORT_MODULE()

RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSString*, getRandomBase64:(double)byteLength) {
NSMutableData *data = [NSMutableData dataWithLength:(NSUInteger)byteLength];
int result = SecRandomCopyBytes(kSecRandomDefault, (NSUInteger)byteLength, data.mutableBytes);
if (result != errSecSuccess) {
@throw([NSException exceptionWithName:@"NO_RANDOM_BYTES" reason:@"Failed to aquire secure random bytes" userInfo:nil]);
}
return [data base64EncodedStringWithOptions:0];
}

#if RCT_NEW_ARCH_ENABLED
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params {
return std::make_shared<facebook::react::NativeRNGetRandomValuesSpecJSI>(params);
}
#endif

@end
12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"fast-base64-decode": "^1.0.0"
},
"peerDependencies": {
"react-native": ">=0.56"
"react-native": ">=0.71"
},
"keywords": [
"Crypto.getRandomValues",
Expand All @@ -16,5 +16,13 @@
"getRandomValues",
"polyfill",
"react-native"
]
],
"codegenConfig": {
"name": "RNGetRandomValuesSpec",
"type": "modules",
"jsSrcsDir": "specs",
"android": {
"javaPackageName": "org.linusu"
}
}
}
9 changes: 6 additions & 3 deletions react-native-get-random-values.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ Pod::Spec.new do |s|
s.platforms = { :ios => "9.0", :tvos => "9.0", :osx => "10.14" }
s.source = { :git => "https://github.com/LinusU/react-native-get-random-values.git", :tag => "v#{s.version}" }

s.source_files = "ios/**/*.{h,m,swift}"
s.requires_arc = true
s.source_files = "ios/**/*.{h,m,mm,swift}"

s.dependency "React-Core"
if respond_to?(:install_modules_dependencies, true)
install_modules_dependencies(s)
else
s.dependency "React-Core"
end
end
16 changes: 16 additions & 0 deletions specs/NativeRNGetRandomValues.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* @flow strict-local
* @format
*/

import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport';
import type { Int32 } from 'react-native/Libraries/Types/CodegenTypes';
import { TurboModuleRegistry } from 'react-native';

export interface Spec extends TurboModule {
+getRandomBase64: (byteLength: Int32) => string;
}

export default (TurboModuleRegistry.get<Spec>(
"RNGetRandomValues"
): Spec);