Commit 45bbfef
authored
feat(Worklets): custom serialization support (#8600)
## Summary
Adding a feature to register Custom Serializables - a way to transfer
objects between runtimes that can't be trivially serialized or
deserialized - like primitives, or objects without circular references,
containing only primitives. The user can register that certain objects
need "packing" before serializing and "unpacking" after deserialization.
For the time being the API is going to be JS only. For an object to be
considered a potential Custom Serializable it __must have a custom
prototype, different than just `Object`__.
### API
The user registers a Custom Serializable with the
`registerCustomSerializable` function:
```ts
function registerCustomSerializable<
TValue extends object,
TSerialized extends object,
>(registrationData: RegistrationData<TValue, TSerialized>);
type RegistrationData<
TValue extends object,
TSerialized extends object,
> = {
name: string;
determine: (value: object) => value is TValue;
pack: (value: TValue) => TSerialized;
unpack: (value: TSerialized) => TValue;
};
```
where:
- `name` is the user-specified name for the Custom Serializable. It's
used to prevent registering the same Custom Serializable twice, i.e.
during hot-reload.
- `determine` is a __worklet__ that receives an `object` type and
returns a boolean that tells if the object is an instance of `TValue`,
that is a known type for packing and unpacking.
- `pack` is a __worklet__ that receives a `TValue` that passed the
`determine` checks and returns an object that can be trivially
serialized, `TPacked`.
- `unpack` is a __worklet__ that receives a `TPacked` objects and
unpacks it to the `TValue` object for future use.
All these functions are called by Worklets, so the packing and unpacking
process is hidden from them.
### Example use (with Nitro Hybrid Objects)
```ts
import { createMMKV, type MMKV } from 'react-native-mmkv';
import { type HybridObject, NitroModules } from 'react-native-nitro-modules';
import type { BoxedHybridObject } from 'react-native-nitro-modules';
import { registerCustomSerializable, scheduleOnUI } from 'react-native-worklets';
const storage: createMMKV(); // MMKV instance can't be trivially serialized, it has a custom prototype.
storage.set('key', 42);
const determine = (value: object) => {
'worklet';
return NitroModules.isHybridObject(value); // `NitroModules.isHybridObject` is the source of truth.
};
const pack = (value: HybridObject<never>) => {
'worklet';
return NitroModules.box(value); // `.box()` method creates a HostObject, which is trivially serializable.
};
const unpack = (value: BoxedHybridObject<HybridObject<never>>) => {
'worklet';
return value.unbox(); // `.unbox()` method extracts the HostObject to an object with the customn prototype.
};
registerCustomSerializable({
name: 'nitro::HybridObject',
determine,
pack,
unpack,
});
scheduleOnUI(() => {
'worklet';
const value = storage.getNumber('key'); // `storage` was implicitly packed on the RN Runtime and unpacked on the UI Runtime.
console.log(value); // 42
});
```
### Implementation details
React Native runtime is the source of truth here. When a new type of a
Serializable is registered, the registration data is __forwarded
synchronously to all active runtimes__ and registered there. This way
all runtimes are consistent and all of them can accept/send the new type
of an object. The registrations are supposed to be rare so I don't think
we should consider it a bottleneck.
Registrations are also saved in new `MemoryManager` class. When a new
Worklet Runtime is created `MemoryManager` loads all Custom Serializable
info on it.
## Test plan
Added runtime test suite.
---
Docs will land after we decide if the current form of the API is
sufficient.1 parent 7bd206b commit 45bbfef
File tree
30 files changed
+953
-7
lines changed- apps
- common-app
- src/apps/reanimated/examples/RuntimeTests
- tests/memory
- fabric-example/ios
- macos-example
- packages/react-native-worklets
- Common/cpp/worklets
- NativeModules
- Resources
- WorkletRuntime
- scripts
- src
- WorkletsModule
- initializers
- memory
30 files changed
+953
-7
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
| 38 | + | |
| 39 | + | |
38 | 40 | | |
39 | 41 | | |
40 | 42 | | |
| |||
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
| 51 | + | |
| 52 | + | |
51 | 53 | | |
52 | 54 | | |
53 | 55 | | |
| |||
apps/common-app/src/apps/reanimated/examples/RuntimeTests/tests/memory/customSerializable.test.tsx
Lines changed: 266 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
0 commit comments