Skip to content

Commit a53cd20

Browse files
christophpurrermeta-codesync[bot]
authored andcommitted
Add ArrayBuffer sample methods to TurboModule examples (#56690)
Summary: Pull Request resolved: #56690 ## Changelog: [General] [Added] - Add ArrayBuffer sample methods to TurboModule examples react-native-community/discussions-and-proposals#947 Add `getArrayBuffer` method to NativeCxxModuleExample and NativeSampleTurboModule specs to demonstrate and validate ArrayBuffer support across all platforms. - **JS Specs:** Added `getArrayBuffer: (arg: ArrayBuffer) => ArrayBuffer` to both NativeCxxModuleExample.js and NativeSampleTurboModule.js - **C++:** Implemented in NativeCxxModuleExample.cpp using `OwnedMutableBuffer` to copy and return the ArrayBuffer - **Java/Kotlin:** Implemented in SampleTurboModule.kt with `ByteBuffer` param/return - **ObjC:** Implemented in RCTSampleTurboModule.mm (iOS + macOS) with `NSData *` param/return Differential Revision: D95652569
1 parent f8f6c5d commit a53cd20

14 files changed

Lines changed: 142 additions & 1 deletion

File tree

packages/react-native/React/Base/RCTConvert.mm

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,24 @@ +(type *)type : (id)json \
6060
RCT_JSON_CONVERTER(NSNumber)
6161

6262
RCT_CUSTOM_CONVERTER(NSSet *, NSSet, [NSSet setWithArray:json])
63-
RCT_CUSTOM_CONVERTER(NSData *, NSData, [json dataUsingEncoding:NSUTF8StringEncoding])
63+
64+
+ (NSData *)NSData:(id)json RCT_DYNAMIC
65+
{
66+
// Return NSData as-is (e.g., when bridging ArrayBuffer from JS).
67+
if ([json isKindOfClass:[NSData class]]) {
68+
return json;
69+
}
70+
if (!RCT_DEBUG) {
71+
return [json dataUsingEncoding:NSUTF8StringEncoding];
72+
} else {
73+
@try {
74+
return [json dataUsingEncoding:NSUTF8StringEncoding];
75+
} @catch (__unused NSException *e) {
76+
RCTLogConvertError(json, @"NSData");
77+
return nil;
78+
}
79+
}
80+
}
6481

6582
+ (NSIndexSet *)NSIndexSet:(id)json
6683
{

packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/NativeSampleTurboModuleSpec.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.facebook.react.bridge.WritableMap;
2222
import com.facebook.react.common.build.ReactBuildConfig;
2323
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
24+
import java.nio.ByteBuffer;
2425
import java.util.Arrays;
2526
import java.util.HashSet;
2627
import java.util.Map;
@@ -165,4 +166,10 @@ public void promiseAssert(Promise promise) {}
165166
@ReactMethod
166167
@DoNotStrip
167168
public void getImageUrl(Promise promise) {}
169+
170+
@ReactMethod(isBlockingSynchronousMethod = true)
171+
@DoNotStrip
172+
public ByteBuffer getArrayBuffer(ByteBuffer arg) {
173+
return null;
174+
}
168175
}

packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,24 @@ __hostFunction_NativeSampleTurboModuleSpecJSI_getImageUrl(
328328
cachedMethodId);
329329
}
330330

331+
static facebook::jsi::Value
332+
__hostFunction_NativeSampleTurboModuleSpecJSI_getArrayBuffer(
333+
facebook::jsi::Runtime& rt,
334+
TurboModule& turboModule,
335+
const facebook::jsi::Value* args,
336+
size_t count) {
337+
static jmethodID cachedMethodId = nullptr;
338+
return static_cast<JavaTurboModule&>(turboModule)
339+
.invokeJavaMethod(
340+
rt,
341+
ArrayBufferKind,
342+
"getArrayBuffer",
343+
"(Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer;",
344+
args,
345+
count,
346+
cachedMethodId);
347+
}
348+
331349
NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(
332350
const JavaTurboModule::InitParams& params)
333351
: JavaTurboModule(params) {
@@ -393,6 +411,9 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(
393411
methodMap_["getImageUrl"] = MethodMetadata{
394412
.argCount = 0,
395413
.invoker = __hostFunction_NativeSampleTurboModuleSpecJSI_getImageUrl};
414+
methodMap_["getArrayBuffer"] = MethodMetadata{
415+
.argCount = 1,
416+
.invoker = __hostFunction_NativeSampleTurboModuleSpecJSI_getArrayBuffer};
396417
eventEmitterMap_["onPress"] =
397418
std::make_shared<AsyncEventEmitter<folly::dynamic>>();
398419
eventEmitterMap_["onClick"] =

packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/SampleTurboModule.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import com.facebook.react.bridge.WritableNativeMap
2727
import com.facebook.react.module.annotations.ReactModule
2828
import com.facebook.react.turbomodule.core.interfaces.BindingsInstallerHolder
2929
import com.facebook.react.turbomodule.core.interfaces.TurboModuleWithJSIBindings
30+
import java.nio.ByteBuffer
3031
import java.util.UUID
3132

3233
@DoNotStrip
@@ -225,6 +226,13 @@ public class SampleTurboModule(private val context: ReactApplicationContext) :
225226
assert(false) { "Intentional assert from JVM promiseAssert" }
226227
}
227228

229+
@DoNotStrip
230+
@Suppress("unused")
231+
override fun getArrayBuffer(arg: ByteBuffer): ByteBuffer {
232+
log("getArrayBuffer", arg, arg)
233+
return arg
234+
}
235+
228236
@DoNotStrip
229237
@Suppress("unused")
230238
override fun getImageUrl(promise: Promise) {

packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ inline JS::NativeSampleTurboModule::Constants::Builder::Builder(Constants i)
104104
- (NSDictionary *)getObjectAssert:(NSDictionary *)arg;
105105
- (void)promiseAssert:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject;
106106
- (void)getImageUrl:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject;
107+
- (NSData *)getArrayBuffer:(NSData *)arg;
107108
- (facebook::react::ModuleConstants<JS::NativeSampleTurboModule::Constants>)constantsToExport;
108109
- (facebook::react::ModuleConstants<JS::NativeSampleTurboModule::Constants>)getConstants;
109110

packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.mm

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,16 @@ - (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallb
224224
.invokeObjCMethod(rt, PromiseKind, "getImageUrl", @selector(getImageUrl:reject:), args, count);
225225
}
226226

227+
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getArrayBuffer(
228+
facebook::jsi::Runtime &rt,
229+
TurboModule &turboModule,
230+
const facebook::jsi::Value *args,
231+
size_t count)
232+
{
233+
return static_cast<ObjCTurboModule &>(turboModule)
234+
.invokeObjCMethod(rt, ArrayBufferKind, "getArrayBuffer", @selector(getArrayBuffer:), args, count);
235+
}
236+
227237
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants(
228238
facebook::jsi::Runtime &rt,
229239
TurboModule &turboModule,
@@ -277,6 +287,9 @@ - (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallb
277287

278288
methodMap_["getImageUrl"] = MethodMetadata{0, __hostFunction_NativeSampleTurboModuleSpecJSI_getImageUrl};
279289

290+
methodMap_["getArrayBuffer"] =
291+
MethodMetadata{.argCount = 1, .invoker = __hostFunction_NativeSampleTurboModuleSpecJSI_getArrayBuffer};
292+
280293
methodMap_["getConstants"] = MethodMetadata{0, __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants};
281294

282295
eventEmitterMap_["onPress"] = std::make_shared<AsyncEventEmitter<id>>();

packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@ - (void)installJSIBindingsWithRuntime:(facebook::jsi::Runtime &)runtime
210210
RCTAssert(false, @"Intentional assert from ObjC promiseAssert");
211211
}
212212

213+
RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSData *, getArrayBuffer : (NSData *)arg)
214+
{
215+
return arg;
216+
}
217+
213218
@end
214219

215220
Class _Nonnull RCTSampleTurboModuleCls(void)

packages/react-native/src/private/specs_DEPRECATED/modules/NativeSampleTurboModule.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export interface Spec extends TurboModule {
4747
+getNumber: (arg: number) => number;
4848
+getString: (arg: string) => string;
4949
+getArray: (arg: Array<any>) => Array<any>;
50+
+getArrayBuffer: (arg: ArrayBuffer) => ArrayBuffer;
5051
+getObject: (arg: Object) => Object;
5152
+getUnsafeObject: (arg: UnsafeObject) => UnsafeObject;
5253
+getRootTag: (arg: RootTag) => RootTag;

packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
#include "NativeCxxModuleExample.h"
9+
#include <react/bridging/ArrayBuffer.h>
910
#include <react/debug/react_native_assert.h>
1011
#include <iomanip>
1112
#include <ostream>
@@ -265,4 +266,14 @@ AsyncPromise<> NativeCxxModuleExample::promiseAssert(jsi::Runtime& rt) {
265266
return promise;
266267
};
267268

269+
jsi::ArrayBuffer NativeCxxModuleExample::getArrayBuffer(
270+
jsi::Runtime& rt,
271+
jsi::ArrayBuffer arg) {
272+
// Return a copy of the input ArrayBuffer
273+
auto size = arg.size(rt);
274+
auto data = arg.data(rt);
275+
auto buffer = std::make_shared<OwnedMutableBuffer>(data, size);
276+
return {rt, std::move(buffer)};
277+
}
278+
268279
} // namespace facebook::react

packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ class NativeCxxModuleExample : public NativeCxxModuleExampleCxxSpec<NativeCxxMod
182182

183183
AsyncPromise<> promiseAssert(jsi::Runtime &rt);
184184

185+
jsi::ArrayBuffer getArrayBuffer(jsi::Runtime &rt, jsi::ArrayBuffer arg);
186+
185187
private:
186188
std::optional<AsyncCallback<std::string>> valueCallback_;
187189
};

0 commit comments

Comments
 (0)