react-native 0.88.0-rc.1 → 0.88.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Libraries/Core/ReactNativeVersion.js +1 -1
- package/React/Base/RCTVersion.m +1 -1
- package/React/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h +3 -4
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +1 -1
- package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
- package/ReactCommon/react/nativemodule/core/iostests/RCTTurboModuleTests.mm +18 -65
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.h +1 -2
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm +1 -2
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h +2 -9
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm +33 -71
- package/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm +8 -19
- package/package.json +13 -10
- package/React/Base/RCTArrayBuffer.h +0 -64
- package/React/Base/RCTArrayBuffer.mm +0 -127
|
@@ -29,7 +29,7 @@ export default class ReactNativeVersion {
|
|
|
29
29
|
static major: number = 0;
|
|
30
30
|
static minor: number = 88;
|
|
31
31
|
static patch: number = 0;
|
|
32
|
-
static prerelease: string | null = 'rc.
|
|
32
|
+
static prerelease: string | null = 'rc.2';
|
|
33
33
|
|
|
34
34
|
static getVersionString(): string {
|
|
35
35
|
return `${this.major}.${this.minor}.${this.patch}${this.prerelease != null ? `-${this.prerelease}` : ''}`;
|
package/React/Base/RCTVersion.m
CHANGED
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
#import <RCTRequired/RCTRequired.h>
|
|
24
24
|
#import <RCTTypeSafety/RCTConvertHelpers.h>
|
|
25
25
|
#import <RCTTypeSafety/RCTTypedModuleConstants.h>
|
|
26
|
-
#import <React/RCTArrayBuffer.h>
|
|
27
26
|
#import <React/RCTBridgeModule.h>
|
|
28
27
|
#import <React/RCTCxxConvert.h>
|
|
29
28
|
#import <React/RCTManagedPointer.h>
|
|
@@ -1779,9 +1778,9 @@ namespace JS {
|
|
|
1779
1778
|
- (NSDictionary *)getValue:(double)x
|
|
1780
1779
|
y:(NSString *)y
|
|
1781
1780
|
z:(NSDictionary *)z;
|
|
1782
|
-
- (
|
|
1783
|
-
- (
|
|
1784
|
-
- (void)processAsyncBuffer:(
|
|
1781
|
+
- (NSMutableData *)getArrayBuffer:(NSMutableData *)buffer;
|
|
1782
|
+
- (NSMutableData *)createNativeBuffer:(double)size;
|
|
1783
|
+
- (void)processAsyncBuffer:(NSMutableData *)payload
|
|
1785
1784
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
1786
1785
|
reject:(RCTPromiseRejectBlock)reject;
|
|
1787
1786
|
- (void)getValueWithCallback:(RCTResponseSenderBlock)callback;
|
|
@@ -7,10 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
#import <XCTest/XCTest.h>
|
|
9
9
|
|
|
10
|
-
#import <React/RCTArrayBuffer.h>
|
|
11
10
|
#import <ReactCommon/RCTTurboModule.h>
|
|
12
11
|
#import <hermes/hermes.h>
|
|
13
|
-
#import <jsi/decorator.h>
|
|
14
12
|
#import <react/featureflags/ReactNativeFeatureFlags.h>
|
|
15
13
|
#import <react/featureflags/ReactNativeFeatureFlagsDefaults.h>
|
|
16
14
|
|
|
@@ -94,39 +92,6 @@ class TestMutableBuffer : public facebook::jsi::MutableBuffer {
|
|
|
94
92
|
std::vector<uint8_t> bytes_;
|
|
95
93
|
};
|
|
96
94
|
|
|
97
|
-
// `jsi::Runtime::tryGetMutableBuffer` is optional — the Hermes branch linked into apps returns
|
|
98
|
-
// nullptr for every ArrayBuffer — so decorate the runtime to answer it for the buffers created
|
|
99
|
-
// through it. That keeps the coverage of the native-backed path independent of the engine.
|
|
100
|
-
// The registry is weak, so the only owners of a backing store remain the JS ArrayBuffer and
|
|
101
|
-
// whatever the conversion retains.
|
|
102
|
-
class MutableBufferAwareRuntime final : public facebook::jsi::RuntimeDecorator<facebook::jsi::Runtime> {
|
|
103
|
-
public:
|
|
104
|
-
explicit MutableBufferAwareRuntime(facebook::jsi::Runtime &plain) : RuntimeDecorator(plain) {}
|
|
105
|
-
|
|
106
|
-
facebook::jsi::ArrayBuffer createArrayBuffer(std::shared_ptr<facebook::jsi::MutableBuffer> buffer) override
|
|
107
|
-
{
|
|
108
|
-
auto arrayBuffer = RuntimeDecorator::createArrayBuffer(buffer);
|
|
109
|
-
buffers_.push_back(buffer);
|
|
110
|
-
return arrayBuffer;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
std::shared_ptr<facebook::jsi::MutableBuffer> tryGetMutableBuffer(
|
|
114
|
-
const facebook::jsi::ArrayBuffer &arrayBuffer) override
|
|
115
|
-
{
|
|
116
|
-
uint8_t *data = arrayBuffer.data(*this);
|
|
117
|
-
for (const auto &weakBuffer : buffers_) {
|
|
118
|
-
auto buffer = weakBuffer.lock();
|
|
119
|
-
if (buffer != nullptr && buffer->data() == data) {
|
|
120
|
-
return buffer;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return nullptr;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
private:
|
|
127
|
-
std::vector<std::weak_ptr<facebook::jsi::MutableBuffer>> buffers_;
|
|
128
|
-
};
|
|
129
|
-
|
|
130
95
|
class StubNativeMethodCallInvoker : public NativeMethodCallInvoker {
|
|
131
96
|
public:
|
|
132
97
|
void invokeAsync(const std::string &methodName, NativeMethodCallFunc &&func) noexcept override
|
|
@@ -354,46 +319,34 @@ class ExceptionCapturingNativeMethodCallInvoker : public NativeMethodCallInvoker
|
|
|
354
319
|
XCTAssertNotNil(original.callStackSymbols);
|
|
355
320
|
}
|
|
356
321
|
|
|
357
|
-
// A
|
|
358
|
-
// the
|
|
359
|
-
|
|
322
|
+
// A JS ArrayBuffer converts to an NSMutableData that owns an independent copy of
|
|
323
|
+
// the bytes — NSMutableData cannot alias a foreign buffer, so the result stays
|
|
324
|
+
// valid and is safe to mutate after the source buffer is gone. This covers the
|
|
325
|
+
// ArrayBuffer-backed-by-native-MutableBuffer case, which is the one that could in
|
|
326
|
+
// principle have been aliased zero-copy.
|
|
327
|
+
- (void)testArrayBufferConvertsToIndependentNSMutableData
|
|
360
328
|
{
|
|
361
329
|
constexpr size_t kBufferSize = 64 * 1024;
|
|
362
330
|
|
|
363
331
|
auto hermesRuntime = facebook::hermes::makeHermesRuntime();
|
|
364
|
-
|
|
332
|
+
facebook::jsi::Runtime *rt = hermesRuntime.get();
|
|
365
333
|
|
|
366
334
|
auto buffer = std::make_shared<TestMutableBuffer>(kBufferSize);
|
|
367
335
|
*buffer->data() = 0xAB;
|
|
368
|
-
const uint8_t *sourceBytes = buffer->data();
|
|
369
|
-
|
|
370
|
-
RCTArrayBuffer *converted = nil;
|
|
371
|
-
{
|
|
372
|
-
facebook::jsi::ArrayBuffer arrayBuffer(runtime, buffer);
|
|
373
|
-
const long ownersBeforeConversion = buffer.use_count();
|
|
374
|
-
|
|
375
|
-
id result = TurboModuleConvertUtils::convertJSIValueToObjCObject(
|
|
376
|
-
runtime, facebook::jsi::Value(runtime, arrayBuffer), nullptr, NO, NO);
|
|
377
|
-
XCTAssertTrue([result isKindOfClass:[RCTArrayBuffer class]]);
|
|
378
|
-
converted = (RCTArrayBuffer *)result;
|
|
379
|
-
|
|
380
|
-
XCTAssertEqual(
|
|
381
|
-
buffer.use_count(), ownersBeforeConversion + 1, @"The RCTArrayBuffer must retain the backing MutableBuffer");
|
|
382
|
-
}
|
|
383
336
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
337
|
+
facebook::jsi::ArrayBuffer arrayBuffer(*rt, buffer);
|
|
338
|
+
id converted =
|
|
339
|
+
TurboModuleConvertUtils::convertJSIValueToObjCObject(*rt, facebook::jsi::Value(*rt, arrayBuffer), nullptr);
|
|
387
340
|
|
|
388
|
-
|
|
389
|
-
*
|
|
390
|
-
XCTAssertEqual(
|
|
391
|
-
*static_cast<uint8_t *>(
|
|
392
|
-
XCTAssertEqual(*buffer->data(), 0xEF);
|
|
341
|
+
XCTAssertTrue([converted isKindOfClass:[NSMutableData class]]);
|
|
342
|
+
NSMutableData *data = (NSMutableData *)converted;
|
|
343
|
+
XCTAssertEqual(data.length, (NSUInteger)kBufferSize);
|
|
344
|
+
XCTAssertEqual(*static_cast<const uint8_t *>(data.bytes), 0xAB);
|
|
393
345
|
|
|
394
|
-
//
|
|
395
|
-
|
|
396
|
-
|
|
346
|
+
// Independent copy: mutating the NSMutableData must not write through to the
|
|
347
|
+
// source MutableBuffer.
|
|
348
|
+
*static_cast<uint8_t *>(data.mutableBytes) = 0xCD;
|
|
349
|
+
XCTAssertEqual(*buffer->data(), 0xAB, @"NSMutableData must not alias the source buffer");
|
|
397
350
|
}
|
|
398
351
|
|
|
399
352
|
@end
|
package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.h
CHANGED
|
@@ -75,8 +75,7 @@ class JSI_EXPORT ObjCInteropTurboModule : public ObjCTurboModule {
|
|
|
75
75
|
const jsi::Value &arg,
|
|
76
76
|
size_t i,
|
|
77
77
|
NSInvocation *inv,
|
|
78
|
-
NSMutableArray *retainedObjectsForInvocation
|
|
79
|
-
bool mustCopyBytes) override;
|
|
78
|
+
NSMutableArray *retainedObjectsForInvocation) override;
|
|
80
79
|
|
|
81
80
|
private:
|
|
82
81
|
std::vector<MethodDescriptor> methodDescriptors_;
|
package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm
CHANGED
|
@@ -363,8 +363,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
|
|
363
363
|
const jsi::Value &jsiArg,
|
|
364
364
|
size_t index,
|
|
365
365
|
NSInvocation *inv,
|
|
366
|
-
NSMutableArray *retainedObjectsForInvocation
|
|
367
|
-
[[maybe_unused]] bool mustCopyBytes)
|
|
366
|
+
NSMutableArray *retainedObjectsForInvocation)
|
|
368
367
|
{
|
|
369
368
|
NSString *methodName = @(methodNameCStr);
|
|
370
369
|
std::string methodJsSignature = name_ + "." + methodNameCStr + "()";
|
|
@@ -35,8 +35,7 @@ id convertJSIValueToObjCObject(
|
|
|
35
35
|
jsi::Runtime &runtime,
|
|
36
36
|
const jsi::Value &value,
|
|
37
37
|
const std::shared_ptr<CallInvoker> &jsInvoker,
|
|
38
|
-
BOOL useNSNull = NO
|
|
39
|
-
BOOL mustCopyBytes = YES);
|
|
38
|
+
BOOL useNSNull = NO);
|
|
40
39
|
} // namespace TurboModuleConvertUtils
|
|
41
40
|
|
|
42
41
|
template <>
|
|
@@ -114,9 +113,6 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule {
|
|
|
114
113
|
* ObjCInteropTurboModule relies heavily on RCTConvert to convert arguments from JavaScript values to Objective C
|
|
115
114
|
* values. ObjCTurboModule tries to minimize reliance on RCTConvert: RCTConvert uses the RCT_EXPORT_METHOD macros,
|
|
116
115
|
* which we want to remove long term from React Native.
|
|
117
|
-
*
|
|
118
|
-
* mustCopyBytes says whether the invocation may outlive the JS call, in which case ArrayBuffer arguments must be
|
|
119
|
-
* copied rather than aliased.
|
|
120
116
|
*/
|
|
121
117
|
virtual void setInvocationArg(
|
|
122
118
|
jsi::Runtime &runtime,
|
|
@@ -125,8 +121,7 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule {
|
|
|
125
121
|
const jsi::Value &arg,
|
|
126
122
|
size_t i,
|
|
127
123
|
NSInvocation *inv,
|
|
128
|
-
NSMutableArray *retainedObjectsForInvocation
|
|
129
|
-
bool mustCopyBytes);
|
|
124
|
+
NSMutableArray *retainedObjectsForInvocation);
|
|
130
125
|
|
|
131
126
|
private:
|
|
132
127
|
// Does the NativeModule dispatch async methods to the JS thread?
|
|
@@ -142,13 +137,11 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule {
|
|
|
142
137
|
NSDictionary<NSString *, NSArray<NSString *> *> *methodArgumentTypeNames_;
|
|
143
138
|
|
|
144
139
|
bool isMethodSync(TurboModuleMethodValueKind returnType);
|
|
145
|
-
bool mustCopyJSHeapArrayBufferBytes(TurboModuleMethodValueKind returnType);
|
|
146
140
|
BOOL hasMethodArgConversionSelector(NSString *methodName, size_t argIndex);
|
|
147
141
|
SEL getMethodArgConversionSelector(NSString *methodName, size_t argIndex);
|
|
148
142
|
NSInvocation *createMethodInvocation(
|
|
149
143
|
jsi::Runtime &runtime,
|
|
150
144
|
bool isSync,
|
|
151
|
-
bool mustCopyBytes,
|
|
152
145
|
const char *methodName,
|
|
153
146
|
SEL selector,
|
|
154
147
|
const jsi::Value *args,
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
#import "RCTTurboModule.h"
|
|
9
9
|
|
|
10
|
-
#import <React/RCTArrayBuffer.h>
|
|
11
10
|
#import <React/RCTBridgeModule.h>
|
|
12
11
|
#import <React/RCTConvert.h>
|
|
13
12
|
#import <React/RCTCxxConvert.h>
|
|
@@ -90,43 +89,35 @@ static std::vector<jsi::Value> convertNSArrayToStdVector(jsi::Runtime &runtime,
|
|
|
90
89
|
return result;
|
|
91
90
|
}
|
|
92
91
|
|
|
93
|
-
static jsi::ArrayBuffer
|
|
92
|
+
static jsi::ArrayBuffer convertNSMutableDataToJSIArrayBuffer(jsi::Runtime &runtime, NSMutableData *value)
|
|
94
93
|
{
|
|
95
|
-
class
|
|
94
|
+
class NSMutableDataBuffer final : public jsi::MutableBuffer {
|
|
96
95
|
public:
|
|
97
|
-
explicit
|
|
98
|
-
: buffer_(buffer), data_(static_cast<uint8_t *>(buffer.mutableBytes)), size_(buffer.length)
|
|
99
|
-
{
|
|
100
|
-
}
|
|
96
|
+
explicit NSMutableDataBuffer(NSMutableData *data) : data_(data) {}
|
|
101
97
|
|
|
102
98
|
size_t size() const override
|
|
103
99
|
{
|
|
104
|
-
return
|
|
100
|
+
return data_.length;
|
|
105
101
|
}
|
|
106
102
|
|
|
107
103
|
uint8_t *data() override
|
|
108
104
|
{
|
|
109
|
-
return data_;
|
|
105
|
+
return static_cast<uint8_t *>(data_.mutableBytes);
|
|
110
106
|
}
|
|
111
107
|
|
|
112
108
|
private:
|
|
113
|
-
|
|
114
|
-
[[maybe_unused]] RCTArrayBuffer *buffer_;
|
|
115
|
-
uint8_t *data_;
|
|
116
|
-
size_t size_;
|
|
109
|
+
NSMutableData *data_;
|
|
117
110
|
};
|
|
118
111
|
|
|
119
|
-
// nil would yield a NULL pointer
|
|
112
|
+
// A nil NSMutableData would silently yield a NULL `mutableBytes` pointer
|
|
113
|
+
// (ObjC nil-messaging) and corrupt the resulting ArrayBuffer. Substitute a
|
|
114
|
+
// fresh empty NSMutableData so the wrapped pointer is always well-defined.
|
|
120
115
|
if (value == nil) {
|
|
121
|
-
RCTLogWarn(@"
|
|
122
|
-
value = [
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (!value.isOwningBytes) {
|
|
126
|
-
value = [RCTArrayBuffer arrayBufferWithCopiedBytes:value.mutableBytes length:value.length];
|
|
116
|
+
RCTLogWarn(@"convertNSMutableDataToJSIArrayBuffer: received nil NSMutableData; returning empty ArrayBuffer");
|
|
117
|
+
value = [NSMutableData data];
|
|
127
118
|
}
|
|
128
|
-
|
|
129
|
-
return {runtime, std::
|
|
119
|
+
auto buffer = std::make_shared<NSMutableDataBuffer>(value);
|
|
120
|
+
return {runtime, std::move(buffer)};
|
|
130
121
|
}
|
|
131
122
|
|
|
132
123
|
jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value)
|
|
@@ -142,8 +133,8 @@ jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value)
|
|
|
142
133
|
return convertNSDictionaryToJSIObject(runtime, (NSDictionary *)value);
|
|
143
134
|
} else if ([value isKindOfClass:[NSArray class]]) {
|
|
144
135
|
return convertNSArrayToJSIArray(runtime, (NSArray *)value);
|
|
145
|
-
} else if ([value isKindOfClass:[
|
|
146
|
-
return
|
|
136
|
+
} else if ([value isKindOfClass:[NSMutableData class]]) {
|
|
137
|
+
return convertNSMutableDataToJSIArrayBuffer(runtime, (NSMutableData *)value);
|
|
147
138
|
} else if (value == (id)kCFNull) {
|
|
148
139
|
return jsi::Value::null();
|
|
149
140
|
}
|
|
@@ -210,41 +201,23 @@ convertJSIFunctionToCallback(jsi::Runtime &rt, jsi::Function &&function, const s
|
|
|
210
201
|
};
|
|
211
202
|
}
|
|
212
203
|
|
|
213
|
-
//
|
|
214
|
-
//
|
|
215
|
-
//
|
|
216
|
-
//
|
|
217
|
-
//
|
|
218
|
-
|
|
219
|
-
|
|
204
|
+
// Copy the ArrayBuffer's bytes into an NSMutableData. A zero-copy wrap is not
|
|
205
|
+
// possible here: NSMutableData needs its own resizable backing store and cannot
|
|
206
|
+
// alias a foreign buffer (even via initWithBytesNoCopy:length:deallocator:, which
|
|
207
|
+
// copies eagerly for the mutable subclass). Copying also makes the result safe to
|
|
208
|
+
// retain in a block, store, or dispatch to another thread, regardless of whether
|
|
209
|
+
// the bytes were owned by JS (valid only for this callstack) or by a native
|
|
210
|
+
// MutableBuffer (which the JS ArrayBuffer may GC concurrently).
|
|
211
|
+
static NSMutableData *convertJSIArrayBufferToNSMutableData(jsi::Runtime &rt, const jsi::ArrayBuffer &value)
|
|
220
212
|
{
|
|
221
|
-
|
|
222
|
-
auto keepAlive = std::move(nativeBuffer);
|
|
223
|
-
return [RCTArrayBuffer arrayBufferWithOwnedBytes:keepAlive->data()
|
|
224
|
-
length:keepAlive->size()
|
|
225
|
-
cleanup:^{
|
|
226
|
-
(void)keepAlive;
|
|
227
|
-
}];
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
void *bytes = arrayBuffer.data(rt);
|
|
231
|
-
size_t size = arrayBuffer.size(rt);
|
|
232
|
-
|
|
233
|
-
// The bytes belong to the JS heap -> async call.
|
|
234
|
-
if (mustCopyBytes) {
|
|
235
|
-
return [RCTArrayBuffer arrayBufferWithCopiedBytes:bytes length:size];
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// The bytes belong to the JS heap -> sync call.
|
|
239
|
-
return [RCTArrayBuffer arrayBufferWithUnownedBytes:bytes length:size];
|
|
213
|
+
return [NSMutableData dataWithBytes:value.data(rt) length:value.size(rt)];
|
|
240
214
|
}
|
|
241
215
|
|
|
242
216
|
id convertJSIValueToObjCObject(
|
|
243
217
|
jsi::Runtime &runtime,
|
|
244
218
|
const jsi::Value &value,
|
|
245
219
|
const std::shared_ptr<CallInvoker> &jsInvoker,
|
|
246
|
-
BOOL useNSNull
|
|
247
|
-
BOOL mustCopyBytes)
|
|
220
|
+
BOOL useNSNull)
|
|
248
221
|
{
|
|
249
222
|
if (value.isUndefined() || (value.isNull() && !useNSNull)) {
|
|
250
223
|
return nil;
|
|
@@ -270,7 +243,7 @@ id convertJSIValueToObjCObject(
|
|
|
270
243
|
return convertJSIFunctionToCallback(runtime, o.getFunction(runtime), jsInvoker);
|
|
271
244
|
}
|
|
272
245
|
if (o.isArrayBuffer(runtime)) {
|
|
273
|
-
return
|
|
246
|
+
return convertJSIArrayBufferToNSMutableData(runtime, o.getArrayBuffer(runtime));
|
|
274
247
|
}
|
|
275
248
|
return convertJSIObjectToNSDictionary(runtime, o, jsInvoker, useNSNull);
|
|
276
249
|
}
|
|
@@ -629,11 +602,11 @@ jsi::Value ObjCTurboModule::convertReturnIdToJSIValue(
|
|
|
629
602
|
break;
|
|
630
603
|
}
|
|
631
604
|
case ArrayBufferKind: {
|
|
632
|
-
if (result != nil && ![result isKindOfClass:[
|
|
633
|
-
RCTLogError(@"convertReturnIdToJSIValue: expected
|
|
605
|
+
if (result != nil && ![result isKindOfClass:[NSMutableData class]]) {
|
|
606
|
+
RCTLogError(@"convertReturnIdToJSIValue: expected NSMutableData for ArrayBufferKind, got %@", [result class]);
|
|
634
607
|
break;
|
|
635
608
|
}
|
|
636
|
-
returnValue =
|
|
609
|
+
returnValue = convertNSMutableDataToJSIArrayBuffer(runtime, (NSMutableData *)result);
|
|
637
610
|
break;
|
|
638
611
|
}
|
|
639
612
|
case FunctionKind:
|
|
@@ -710,8 +683,7 @@ void ObjCTurboModule::setInvocationArg(
|
|
|
710
683
|
const jsi::Value &arg,
|
|
711
684
|
size_t i,
|
|
712
685
|
NSInvocation *inv,
|
|
713
|
-
NSMutableArray *retainedObjectsForInvocation
|
|
714
|
-
bool mustCopyBytes)
|
|
686
|
+
NSMutableArray *retainedObjectsForInvocation)
|
|
715
687
|
{
|
|
716
688
|
if (arg.isBool()) {
|
|
717
689
|
bool v = arg.getBool();
|
|
@@ -754,15 +726,13 @@ void ObjCTurboModule::setInvocationArg(
|
|
|
754
726
|
* Convert arg to ObjC objects.
|
|
755
727
|
*/
|
|
756
728
|
BOOL enableModuleArgumentNSNullConversionIOS = ReactNativeFeatureFlags::enableModuleArgumentNSNullConversionIOS();
|
|
757
|
-
id objCArg =
|
|
758
|
-
convertJSIValueToObjCObject(runtime, arg, jsInvoker_, enableModuleArgumentNSNullConversionIOS, mustCopyBytes);
|
|
729
|
+
id objCArg = convertJSIValueToObjCObject(runtime, arg, jsInvoker_, enableModuleArgumentNSNullConversionIOS);
|
|
759
730
|
|
|
760
731
|
// A JS `null` in argument position must reach ObjC as `nil`; only nulls nested inside arrays and
|
|
761
732
|
// dictionaries are preserved as `kCFNull`. Skipping `setArgument:` leaves the slot zeroed.
|
|
762
733
|
if (enableModuleArgumentNSNullConversionIOS && objCArg == (id)kCFNull) {
|
|
763
734
|
return;
|
|
764
735
|
}
|
|
765
|
-
|
|
766
736
|
if (objCArg != nullptr) {
|
|
767
737
|
NSString *methodNameNSString = @(methodName);
|
|
768
738
|
|
|
@@ -823,7 +793,6 @@ void ObjCTurboModule::setInvocationArg(
|
|
|
823
793
|
NSInvocation *ObjCTurboModule::createMethodInvocation(
|
|
824
794
|
jsi::Runtime &runtime,
|
|
825
795
|
bool isSync,
|
|
826
|
-
bool mustCopyBytes,
|
|
827
796
|
const char *methodName,
|
|
828
797
|
SEL selector,
|
|
829
798
|
const jsi::Value *args,
|
|
@@ -852,7 +821,7 @@ NSInvocation *ObjCTurboModule::createMethodInvocation(
|
|
|
852
821
|
for (size_t i = 0; i < count; i++) {
|
|
853
822
|
const jsi::Value &arg = args[i];
|
|
854
823
|
const std::string objCArgType = [methodSignature getArgumentTypeAtIndex:i + 2];
|
|
855
|
-
setInvocationArg(runtime, methodName, objCArgType, arg, i, inv, retainedObjectsForInvocation
|
|
824
|
+
setInvocationArg(runtime, methodName, objCArgType, arg, i, inv, retainedObjectsForInvocation);
|
|
856
825
|
}
|
|
857
826
|
|
|
858
827
|
if (isSync) {
|
|
@@ -873,12 +842,6 @@ bool ObjCTurboModule::isMethodSync(TurboModuleMethodValueKind returnType)
|
|
|
873
842
|
return returnType != VoidKind && returnType != PromiseKind;
|
|
874
843
|
}
|
|
875
844
|
|
|
876
|
-
bool ObjCTurboModule::mustCopyJSHeapArrayBufferBytes(TurboModuleMethodValueKind returnType)
|
|
877
|
-
{
|
|
878
|
-
// Void always dispatches via invokeAsync and promise may.
|
|
879
|
-
return returnType == VoidKind || returnType == PromiseKind;
|
|
880
|
-
}
|
|
881
|
-
|
|
882
845
|
ObjCTurboModule::ObjCTurboModule(const InitParams ¶ms)
|
|
883
846
|
: TurboModule(params.moduleName, params.jsInvoker),
|
|
884
847
|
instance_(params.instance),
|
|
@@ -899,7 +862,6 @@ jsi::Value ObjCTurboModule::invokeObjCMethod(
|
|
|
899
862
|
const char *methodName = methodNameStr.c_str();
|
|
900
863
|
|
|
901
864
|
bool isSyncInvocation = isMethodSync(returnType);
|
|
902
|
-
bool mustCopyBytes = mustCopyJSHeapArrayBufferBytes(returnType);
|
|
903
865
|
|
|
904
866
|
if (isSyncInvocation) {
|
|
905
867
|
TurboModulePerfLogger::syncMethodCallStart(moduleName, methodName);
|
|
@@ -909,7 +871,7 @@ jsi::Value ObjCTurboModule::invokeObjCMethod(
|
|
|
909
871
|
|
|
910
872
|
NSMutableArray *retainedObjectsForInvocation = [NSMutableArray arrayWithCapacity:count + 2];
|
|
911
873
|
NSInvocation *inv = createMethodInvocation(
|
|
912
|
-
runtime, isSyncInvocation,
|
|
874
|
+
runtime, isSyncInvocation, methodName, selector, args, count, retainedObjectsForInvocation);
|
|
913
875
|
|
|
914
876
|
jsi::Value returnValue = jsi::Value::undefined();
|
|
915
877
|
|
package/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm
CHANGED
|
@@ -6,8 +6,6 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
#import "RCTSampleTurboModule.h"
|
|
9
|
-
|
|
10
|
-
#import <React/RCTArrayBuffer.h>
|
|
11
9
|
#import "RCTSampleTurboModulePlugin.h"
|
|
12
10
|
|
|
13
11
|
#import <React/RCTAssert.h>
|
|
@@ -16,8 +14,6 @@
|
|
|
16
14
|
#import <ReactCommon/RCTTurboModuleWithJSIBindings.h>
|
|
17
15
|
#import <UIKit/UIKit.h>
|
|
18
16
|
|
|
19
|
-
#include <span>
|
|
20
|
-
|
|
21
17
|
using namespace facebook::react;
|
|
22
18
|
|
|
23
19
|
@interface RCTSampleTurboModule () <RCTTurboModuleWithJSIBindings, RCTInitializing>
|
|
@@ -149,27 +145,20 @@ RCT_EXPORT_MODULE()
|
|
|
149
145
|
};
|
|
150
146
|
}
|
|
151
147
|
|
|
152
|
-
//
|
|
153
|
-
|
|
148
|
+
// Arguments arrive as an immutable NSData, but an ArrayBuffer return must be
|
|
149
|
+
// NSMutableData: it is handed to JS as a jsi::MutableBuffer, whose data() is
|
|
150
|
+
// non-const. Echoing the argument back therefore needs a mutable copy.
|
|
151
|
+
- (NSMutableData *)getArrayBuffer:(NSData *)buffer
|
|
154
152
|
{
|
|
155
|
-
|
|
156
|
-
if (bytes == nullptr) {
|
|
157
|
-
return buffer;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
std::span<uint8_t> byteSpan(bytes, static_cast<size_t>(buffer.length));
|
|
161
|
-
for (auto &byte : byteSpan) {
|
|
162
|
-
byte = static_cast<uint8_t>(byte * 2);
|
|
163
|
-
}
|
|
164
|
-
return buffer;
|
|
153
|
+
return [buffer mutableCopy];
|
|
165
154
|
}
|
|
166
155
|
|
|
167
|
-
- (
|
|
156
|
+
- (NSMutableData *)createNativeBuffer:(double)size
|
|
168
157
|
{
|
|
169
|
-
return [
|
|
158
|
+
return [NSMutableData dataWithLength:(NSUInteger)size];
|
|
170
159
|
}
|
|
171
160
|
|
|
172
|
-
- (void)processAsyncBuffer:(
|
|
161
|
+
- (void)processAsyncBuffer:(NSData *)payload
|
|
173
162
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
174
163
|
reject:(RCTPromiseRejectBlock)reject
|
|
175
164
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native",
|
|
3
|
-
"version": "0.88.0-rc.
|
|
3
|
+
"version": "0.88.0-rc.2",
|
|
4
4
|
"description": "A framework for building native apps using React",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -34,7 +34,10 @@
|
|
|
34
34
|
"default": "./index.js"
|
|
35
35
|
},
|
|
36
36
|
"./Libraries/*": {
|
|
37
|
-
"react-native-legacy-deep-imports":
|
|
37
|
+
"react-native-legacy-deep-imports": [
|
|
38
|
+
"./types_DEPRECATED/Libraries/*.d.ts",
|
|
39
|
+
"./Libraries/*.d.ts"
|
|
40
|
+
],
|
|
38
41
|
"types": null,
|
|
39
42
|
"default": "./Libraries/*.js"
|
|
40
43
|
},
|
|
@@ -151,12 +154,12 @@
|
|
|
151
154
|
}
|
|
152
155
|
},
|
|
153
156
|
"dependencies": {
|
|
154
|
-
"@react-native/asset-utils": "0.88.0-rc.
|
|
155
|
-
"@react-native/codegen": "0.88.0-rc.
|
|
156
|
-
"@react-native/community-cli-plugin": "0.88.0-rc.
|
|
157
|
-
"@react-native/gradle-plugin": "0.88.0-rc.
|
|
158
|
-
"@react-native/normalize-colors": "0.88.0-rc.
|
|
159
|
-
"@react-native/virtualized-lists": "0.88.0-rc.
|
|
157
|
+
"@react-native/asset-utils": "0.88.0-rc.2",
|
|
158
|
+
"@react-native/codegen": "0.88.0-rc.2",
|
|
159
|
+
"@react-native/community-cli-plugin": "0.88.0-rc.2",
|
|
160
|
+
"@react-native/gradle-plugin": "0.88.0-rc.2",
|
|
161
|
+
"@react-native/normalize-colors": "0.88.0-rc.2",
|
|
162
|
+
"@react-native/virtualized-lists": "0.88.0-rc.2",
|
|
160
163
|
"anser": "^1.4.9",
|
|
161
164
|
"ansi-regex": "^5.0.0",
|
|
162
165
|
"flow-parser": "0.327.0",
|
|
@@ -165,8 +168,8 @@
|
|
|
165
168
|
"hermes-compiler": "260318099.0.3",
|
|
166
169
|
"invariant": "^2.2.4",
|
|
167
170
|
"memoize-one": "^5.0.0",
|
|
168
|
-
"metro-runtime": "^0.87.
|
|
169
|
-
"metro-source-map": "^0.87.
|
|
171
|
+
"metro-runtime": "^0.87.1",
|
|
172
|
+
"metro-source-map": "^0.87.1",
|
|
170
173
|
"nullthrows": "^1.1.1",
|
|
171
174
|
"pretty-format": "^29.7.0",
|
|
172
175
|
"promise": "^8.3.0",
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
#import <Foundation/Foundation.h>
|
|
9
|
-
|
|
10
|
-
NS_ASSUME_NONNULL_BEGIN
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* A fixed-length byte buffer shared between JS `ArrayBuffer`s and ObjC TurboModules. Fixed
|
|
14
|
-
* length lets the backing store alias JS memory; `NSMutableData` cannot do that.
|
|
15
|
-
*
|
|
16
|
-
* `isOwningBytes`:
|
|
17
|
-
* - `YES` — safe to retain and use from any thread (synchronize if aliasing JS
|
|
18
|
-
* memory).
|
|
19
|
-
* - `NO` — valid only during the synchronous call on the calling thread; copy with
|
|
20
|
-
* `arrayBufferWithCopiedBytes:length:` to keep the bytes.
|
|
21
|
-
*/
|
|
22
|
-
@interface RCTArrayBuffer : NSObject
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* NULL when `length` is 0, non-NULL otherwise, matching `NSData.bytes`.
|
|
26
|
-
*/
|
|
27
|
-
@property (nonatomic, readonly, nullable) void *mutableBytes NS_RETURNS_INNER_POINTER;
|
|
28
|
-
|
|
29
|
-
@property (nonatomic, readonly) NSUInteger length;
|
|
30
|
-
|
|
31
|
-
/** Whether the buffer owns its bytes. See the class comment. */
|
|
32
|
-
@property (nonatomic, readonly, getter=isOwningBytes) BOOL owningBytes;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* A new zero-filled owning buffer.
|
|
36
|
-
*/
|
|
37
|
-
+ (instancetype)arrayBufferWithLength:(NSUInteger)length;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* A new owning buffer holding a copy of `bytes`. Passing NULL zero-fills.
|
|
41
|
-
*/
|
|
42
|
-
+ (instancetype)arrayBufferWithCopiedBytes:(const void *_Nullable)bytes length:(NSUInteger)length;
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* An owning buffer aliasing `bytes` without copying. If `cleanup` is non-nil, it runs on dealloc,
|
|
46
|
-
* like `-[NSData dataWithBytesNoCopy:length:freeWhenDone:YES]`; if nil, the caller must keep
|
|
47
|
-
* `bytes` valid until dealloc. NULL `bytes` with non-zero `length` raises NSInvalidArgumentException.
|
|
48
|
-
*/
|
|
49
|
-
+ (instancetype)arrayBufferWithOwnedBytes:(nullable void *)bytes
|
|
50
|
-
length:(NSUInteger)length
|
|
51
|
-
cleanup:(nullable void (^)(void))cleanup;
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* A non-owning, zero-copy alias of `bytes`. See the class comment for lifetime rules. NULL `bytes`
|
|
55
|
-
* with non-zero `length` raises NSInvalidArgumentException.
|
|
56
|
-
*/
|
|
57
|
-
+ (instancetype)arrayBufferWithUnownedBytes:(nullable void *)bytes length:(NSUInteger)length;
|
|
58
|
-
|
|
59
|
-
- (instancetype)init NS_UNAVAILABLE;
|
|
60
|
-
+ (instancetype)new NS_UNAVAILABLE;
|
|
61
|
-
|
|
62
|
-
@end
|
|
63
|
-
|
|
64
|
-
NS_ASSUME_NONNULL_END
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
#import "RCTArrayBuffer.h"
|
|
9
|
-
|
|
10
|
-
#include <cstdint>
|
|
11
|
-
#include <cstring>
|
|
12
|
-
#include <utility>
|
|
13
|
-
#include <vector>
|
|
14
|
-
|
|
15
|
-
@interface RCTArrayBuffer ()
|
|
16
|
-
|
|
17
|
-
- (instancetype)initWithBytesNoCopy:(nullable void *)bytes
|
|
18
|
-
length:(NSUInteger)length
|
|
19
|
-
owningBytes:(BOOL)owningBytes
|
|
20
|
-
cleanup:(nullable void (^)(void))cleanup NS_DESIGNATED_INITIALIZER;
|
|
21
|
-
- (instancetype)initWithCopiedBytes:(const void *_Nullable)bytes length:(NSUInteger)length;
|
|
22
|
-
|
|
23
|
-
@end
|
|
24
|
-
|
|
25
|
-
@implementation RCTArrayBuffer {
|
|
26
|
-
void *_bytes;
|
|
27
|
-
NSUInteger _length;
|
|
28
|
-
BOOL _owningBytes;
|
|
29
|
-
void (^_cleanup)(void);
|
|
30
|
-
std::vector<uint8_t> _copiedBytes;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
#pragma mark - Initializers
|
|
34
|
-
|
|
35
|
-
- (instancetype)initWithBytesNoCopy:(void *)bytes
|
|
36
|
-
length:(NSUInteger)length
|
|
37
|
-
owningBytes:(BOOL)owningBytes
|
|
38
|
-
cleanup:(void (^)(void))cleanup
|
|
39
|
-
{
|
|
40
|
-
if (bytes == NULL && length != 0) {
|
|
41
|
-
[NSException raise:NSInvalidArgumentException
|
|
42
|
-
format:@"RCTArrayBuffer: NULL bytes with length %lu", (unsigned long)length];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (self = [super init]) {
|
|
46
|
-
_bytes = bytes;
|
|
47
|
-
_length = length;
|
|
48
|
-
_owningBytes = owningBytes;
|
|
49
|
-
_cleanup = [cleanup copy];
|
|
50
|
-
}
|
|
51
|
-
return self;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
- (instancetype)initWithCopiedBytes:(const void *)bytes length:(NSUInteger)length
|
|
55
|
-
{
|
|
56
|
-
if (length == 0) {
|
|
57
|
-
return [self initWithBytesNoCopy:NULL length:0 owningBytes:YES cleanup:nil];
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
std::vector<uint8_t> copy(length);
|
|
61
|
-
if (bytes != NULL) {
|
|
62
|
-
std::memcpy(copy.data(), bytes, length);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Moving a vector hands over its heap buffer, so `data()` stays valid in `_copiedBytes`.
|
|
66
|
-
if (self = [self initWithBytesNoCopy:copy.data() length:length owningBytes:YES cleanup:nil]) {
|
|
67
|
-
_copiedBytes = std::move(copy);
|
|
68
|
-
}
|
|
69
|
-
return self;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
+ (instancetype)arrayBufferWithLength:(NSUInteger)length
|
|
73
|
-
{
|
|
74
|
-
return [[self alloc] initWithCopiedBytes:NULL length:length];
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
+ (instancetype)arrayBufferWithCopiedBytes:(const void *)bytes length:(NSUInteger)length
|
|
78
|
-
{
|
|
79
|
-
return [[self alloc] initWithCopiedBytes:bytes length:length];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
+ (instancetype)arrayBufferWithOwnedBytes:(void *)bytes
|
|
83
|
-
length:(NSUInteger)length
|
|
84
|
-
cleanup:(nullable void (^)(void))cleanup
|
|
85
|
-
{
|
|
86
|
-
return [[self alloc] initWithBytesNoCopy:bytes length:length owningBytes:YES cleanup:cleanup];
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
+ (instancetype)arrayBufferWithUnownedBytes:(void *)bytes length:(NSUInteger)length
|
|
90
|
-
{
|
|
91
|
-
return [[self alloc] initWithBytesNoCopy:bytes length:length owningBytes:NO cleanup:nil];
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
#pragma mark - Accessors
|
|
95
|
-
|
|
96
|
-
- (void *)mutableBytes
|
|
97
|
-
{
|
|
98
|
-
return _bytes;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
- (NSUInteger)length
|
|
102
|
-
{
|
|
103
|
-
return _length;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
- (BOOL)isOwningBytes
|
|
107
|
-
{
|
|
108
|
-
return _owningBytes;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
- (NSString *)description
|
|
112
|
-
{
|
|
113
|
-
return [NSString stringWithFormat:@"<%@: %p; length = %lu; owningBytes = %@>",
|
|
114
|
-
NSStringFromClass([self class]),
|
|
115
|
-
self,
|
|
116
|
-
(unsigned long)_length,
|
|
117
|
-
_owningBytes ? @"YES" : @"NO"];
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
- (void)dealloc
|
|
121
|
-
{
|
|
122
|
-
if (_cleanup != nil) {
|
|
123
|
-
_cleanup();
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
@end
|