Skip to content

Commit ba01f97

Browse files
authored
feat(Worklets): use int64 for BigInt when possible (#8557)
## Summary Small optimization that uses int64 type for BigInts whenever they fit in that range. ## Test plan - New runtime tests - I checked in debugger that both paths execute properly.
1 parent 3ee5ed1 commit ba01f97

File tree

4 files changed

+54
-14
lines changed

4 files changed

+54
-14
lines changed

apps/common-app/src/apps/reanimated/examples/RuntimeTests/tests/memory/createSerializable.test.tsx

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
2+
/* eslint-disable @typescript-eslint/no-unsafe-call */
3+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
4+
/* eslint-disable @typescript-eslint/no-explicit-any */
15
import React, { useEffect } from 'react';
26
import { View } from 'react-native';
37
import { useSharedValue } from 'react-native-reanimated';
@@ -32,11 +36,11 @@ const ValueComponent = ({ onRunUIFunction }: { onRunUIFunction: () => boolean })
3236
try {
3337
const result = onRunUIFunction();
3438
sharedResult.value = result ? 'ok' : 'not_ok';
35-
} catch (error) {
39+
} catch {
3640
sharedResult.value = 'error';
3741
}
3842
});
39-
} catch (error) {
43+
} catch {
4044
sharedResult.value = 'error';
4145
}
4246
notify(DONE_NOTIFICATION_NAME);
@@ -178,7 +182,7 @@ describe('Test createSerializable', () => {
178182
expect(sharedValue.onJS).toBe('ok');
179183
});
180184

181-
test('createSerializableBigInt', async () => {
185+
test('createSerializableBigInt fitting in int64', async () => {
182186
// Arrange
183187
const bigIntValue = BigInt(123);
184188

@@ -200,9 +204,31 @@ describe('Test createSerializable', () => {
200204
expect(sharedValue.onJS).toBe('ok');
201205
});
202206

207+
test('createSerializableBigInt too big for uint64', async () => {
208+
// Arrange
209+
const maxInt64 = BigInt('0x7FFFFFFFFFFFFFFF');
210+
const bigIntValue = maxInt64 * maxInt64;
211+
212+
// Act
213+
await render(
214+
<ValueComponent
215+
onRunUIFunction={() => {
216+
'worklet';
217+
const checks = [typeof bigIntValue === 'bigint', bigIntValue === maxInt64 * maxInt64];
218+
return checks.every(Boolean);
219+
}}
220+
/>,
221+
);
222+
await waitForNotification(DONE_NOTIFICATION_NAME);
223+
224+
// Assert
225+
const sharedValue = await getRegisteredValue(RESULT_SHARED_VALUE_REF);
226+
expect(sharedValue.onUI).toBe('ok');
227+
expect(sharedValue.onJS).toBe('ok');
228+
});
229+
203230
test('createSerializableHostObject', async () => {
204231
// Arrange
205-
// @ts-expect-error It's ok
206232
const hostObjectValue = globalThis.__reanimatedModuleProxy;
207233
const hostObjectKeys = Object.keys(hostObjectValue);
208234

@@ -572,8 +598,7 @@ describe('Test createSerializable', () => {
572598

573599
test('createSerializableHostFunction', async () => {
574600
// Arrange
575-
// @ts-expect-error It's ok
576-
const hostFunction = globalThis.__workletsModuleProxy.createSerializableBoolean;
601+
const hostFunction = globalThis.__workletsModuleProxy.createSerializableBoolean as any;
577602

578603
// Act
579604
await render(
@@ -597,7 +622,6 @@ describe('Test createSerializable', () => {
597622

598623
test('createSerializableTurboModuleLike', async () => {
599624
// Arrange
600-
// @ts-expect-error This global host object isn't exposed in the types.
601625
const proto = globalThis.__reanimatedModuleProxy;
602626
const reanimatedModuleKeys = Object.keys(proto);
603627
const obj = {
@@ -751,3 +775,8 @@ describe('Test createSerializable', () => {
751775
expect(sharedValue.onJS).toBe('error');
752776
});
753777
});
778+
779+
declare global {
780+
var __reanimatedModuleProxy: Record<string, unknown>;
781+
var __workletsModuleProxy: Record<string, unknown>;
782+
}

apps/common-app/src/apps/reanimated/examples/RuntimeTests/tests/memory/isSerializableRef.test.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
12
import { isSerializableRef, createSerializable } from 'react-native-worklets';
23
import { describe, expect, test } from '../../ReJest/RuntimeTestsApi';
34

@@ -151,23 +152,20 @@ describe('Test isSerializableRef', () => {
151152
});
152153

153154
test('check if createSerializable<host object> returns serializable ref', () => {
154-
// @ts-expect-error It's ok
155155
const hostObjectValue = globalThis.__reanimatedModuleProxy;
156156
const serializableRef = createSerializable(hostObjectValue);
157157

158158
expect(isSerializableRef(serializableRef)).toBe(true);
159159
});
160160

161161
test('check if createSerializable<host function> returns serializable ref', () => {
162-
// @ts-expect-error It's ok
163162
const hostFunction = globalThis.__workletsModuleProxy.createSerializableBoolean;
164163
const serializableRef = createSerializable(hostFunction);
165164

166165
expect(isSerializableRef(serializableRef)).toBe(true);
167166
});
168167

169168
test('check if createSerializable<TurboModule-like object> returns serializable ref', () => {
170-
// @ts-expect-error This global host object isn't exposed in the types.
171169
const proto = globalThis.__reanimatedModuleProxy;
172170
const obj = {
173171
a: 1,

packages/react-native-worklets/Common/cpp/worklets/SharedItems/Serializable.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,11 @@ jsi::Value SerializableString::toJSValue(jsi::Runtime &rt) {
441441
}
442442

443443
jsi::Value SerializableBigInt::toJSValue(jsi::Runtime &rt) {
444-
return rt.global().getPropertyAsFunction(rt, "BigInt").call(rt, jsi::String::createFromUtf8(rt, string_));
444+
if (fastValue_.has_value()) {
445+
return jsi::BigInt::fromInt64(rt, fastValue_.value());
446+
} else {
447+
return rt.global().getPropertyAsFunction(rt, "BigInt").call(rt, jsi::String::createFromUtf8(rt, slowValue_));
448+
}
445449
}
446450

447451
jsi::Value SerializableScalar::toJSValue(jsi::Runtime &) {

packages/react-native-worklets/Common/cpp/worklets/SharedItems/Serializable.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -364,13 +364,22 @@ class SerializableString : public Serializable {
364364

365365
class SerializableBigInt : public Serializable {
366366
public:
367-
explicit SerializableBigInt(jsi::Runtime &rt, const jsi::BigInt &bigint)
368-
: Serializable(ValueType::BigIntType), string_(bigint.toString(rt).utf8(rt)) {}
367+
explicit SerializableBigInt(jsi::Runtime &rt, const jsi::BigInt &bigInt) : Serializable(ValueType::BigIntType) {
368+
if (bigInt.isInt64(rt)) {
369+
fastValue_ = bigInt.getInt64(rt);
370+
} else {
371+
slowValue_ = bigInt.toString(rt).utf8(rt);
372+
}
373+
}
369374

370375
jsi::Value toJSValue(jsi::Runtime &rt) override;
371376

372377
protected:
373-
const std::string string_;
378+
/**
379+
* This member is used only when the BigInt fits into int64_t range.
380+
*/
381+
std::optional<int64_t> fastValue_{};
382+
std::string slowValue_{};
374383
};
375384

376385
class SerializableScalar : public Serializable {

0 commit comments

Comments
 (0)