Skip to content

Commit

Permalink
fix: Recursion in worklets (#6445)
Browse files Browse the repository at this point in the history
## Summary

Turns out that in #6163 I overlooked the fact that we shouldn't rename
React part of worklet functions. This PR changes the naming behavior,
only worklet counterparts are renamed for better error verbosity. See
differences in snapshots for more details.

## Test plan

- [x] Upgraded jest unit tests pass
- [x] New runtime tests pass
  • Loading branch information
tjzel authored Aug 28, 2024
1 parent b7c542f commit eaae44c
Show file tree
Hide file tree
Showing 11 changed files with 1,127 additions and 949 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export default function RuntimeTestsExample() {
require('./tests/plugin/fileWorkletization.test');
require('./tests/plugin/contextObjects.test');
require('./tests/plugin/workletClasses.test');
require('./tests/plugin/recursion.test');
},
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import React, { useEffect } from 'react';
import { View } from 'react-native';
import { useSharedValue, runOnUI, runOnJS } from 'react-native-reanimated';
import { render, wait, describe, getRegisteredValue, registerValue, test, expect } from '../../ReJest/RuntimeTestsApi';

const SHARED_VALUE_REF = 'SHARED_VALUE_REF';

describe('Test recursion in worklets', () => {
test('on Worklet runtime', async () => {
const ExampleComponent = () => {
const output = useSharedValue<number | null>(null);
registerValue(SHARED_VALUE_REF, output);
function recursiveWorklet(a: number) {
if (a === 2) {
output.value = a;
} else {
recursiveWorklet(a + 1);
}
}

useEffect(() => {
runOnUI(recursiveWorklet)(0);
});

return <View />;
};
await render(<ExampleComponent />);
await wait(100);
const sharedValue = await getRegisteredValue(SHARED_VALUE_REF);
expect(sharedValue.onUI).toBe(2);
});

test('on React runtime', async () => {
const ExampleComponent = () => {
const output = useSharedValue<number | null>(null);
registerValue(SHARED_VALUE_REF, output);
function recursiveWorklet(a: number) {
if (a === 2) {
output.value = a;
} else {
recursiveWorklet(a + 1);
}
}

useEffect(() => {
recursiveWorklet(0);
});

return <View />;
};
await render(<ExampleComponent />);
await wait(100);
const sharedValue = await getRegisteredValue(SHARED_VALUE_REF);
expect(sharedValue.onJS).toBe(2);
});

test('from React to Worklet runtime', async () => {
const ExampleComponent = () => {
const output = useSharedValue<number | null>(null);
registerValue(SHARED_VALUE_REF, output);
function recursiveWorklet(a: number) {
if (a === 2) {
output.value = a;
} else if (a === 1) {
runOnUI(recursiveWorklet)(a + 1);
} else {
recursiveWorklet(a + 1);
}
}

useEffect(() => {
recursiveWorklet(0);
});

return <View />;
};
await render(<ExampleComponent />);
await wait(100);
const sharedValue = await getRegisteredValue(SHARED_VALUE_REF);
expect(sharedValue.onUI).toBe(2);
});

test('from Worklet to React runtime', async () => {
const ExampleComponent = () => {
const output = useSharedValue<number | null>(null);
registerValue(SHARED_VALUE_REF, output);
function recursiveWorklet(a: number) {
if (a === 2) {
output.value = a;
} else if (a === 1) {
try {
// TODO: Such case isn't supported at the moment -
// a function can't be a Worklet and a Remote function at the same time.
// Consider supporting it in the future.
runOnJS(recursiveWorklet)(a + 1);
} catch {}
} else {
recursiveWorklet(a + 1);
}
}

useEffect(() => {
runOnUI(recursiveWorklet)(0);
});

return <View />;
};
await render(<ExampleComponent />);
await wait(100);
const sharedValue = await getRegisteredValue(SHARED_VALUE_REF);
expect(sharedValue.onJS).toBe(null);
});
});
Loading

0 comments on commit eaae44c

Please sign in to comment.