Skip to content

Commit

Permalink
Fix cyclic object detection in makeShareableCloneRecursive (softwar…
Browse files Browse the repository at this point in the history
…e-mansion#4475)

## Summary

This PR improves the developer experience when playing around with
Reanimated's internals takes a very bad turn.

Currently, while cloning shareables, we check for cycles by storing the
cloned object at some depth:

https://github.com/software-mansion/react-native-reanimated/blob/4ebd011650e932af12150ed37c27c1cb66d00fd9/src/reanimated2/shareables.ts#L103
Sometimes (not exactly sure when) we clear this variable so we don't
hold it forever:

https://github.com/software-mansion/react-native-reanimated/blob/4ebd011650e932af12150ed37c27c1cb66d00fd9/src/reanimated2/shareables.ts#L110
However, it may happen that while we're deep down in the tree, the
function will be called with `depth = 0` which resets the store and thus
breaks our cyclic object detection mechanism, resulting in a well-known
"Maximum call stack exceeded" error, like here:


![](https://github.com/software-mansion/react-native-reanimated/assets/20516055/6558d757-6fd1-4da5-8db2-3048fbca76f8)

Here's the place where we call `makeShareableClone` recursively without
passing `depth`:


https://github.com/software-mansion/react-native-reanimated/blob/4ebd011650e932af12150ed37c27c1cb66d00fd9/src/reanimated2/shareables.ts#L157-L160

This PR adds the missing argument.

| Before | After |
|:-:|:-:|
| <img width="503" alt="Zrzut ekranu 2023-05-18 o 17 55 30"
src="https://github.com/software-mansion/react-native-reanimated/assets/20516055/bc54b12d-a6cb-4ae3-ad00-18242d85f2c7">
| <img width="503" alt="Zrzut ekranu 2023-05-18 o 17 55 37"
src="https://github.com/software-mansion/react-native-reanimated/assets/20516055/033646e9-6370-49a3-89b1-17adb7833c17">
|

## Test plan

1. Add `'worklet';` directive in `runOnUI` function in `threads.ts`
2. Comment out `makeShareableCloneRecursive(worklet);` inside `runOnUI`
function body
3. Call the following code:
```ts
runOnUI(() => {
  'worklet';
  console.log(_WORKLET, 'Hello from the UI thread!');
  runOnUI;
})();
```
  • Loading branch information
tomekzaw authored and fluiddot committed Jun 5, 2023
1 parent 4299372 commit dd9d942
Showing 1 changed file with 3 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/reanimated2/shareables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,11 @@ export function makeShareableCloneRecursive<T>(
// we request shareable value to persist its UI counterpart. This means
// that the __initData field that contains long strings represeting the
// worklet code, source map, and location, will always be
// serialized/deserialized once. We don't increase depth when calling
// this method as these objects have one level anyways.
// serialized/deserialized once.
toAdapt.__initData = makeShareableCloneRecursive(
value.__initData,
true
true,
depth + 1
);
delete value.__initData;
}
Expand Down

0 comments on commit dd9d942

Please sign in to comment.