Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workletizable Classes #6230

Merged
merged 12 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,6 @@ module.exports = {
'jest/no-identical-title': 'error',
'jest/prefer-to-have-length': 'warn',
'jest/valid-expect': 'error',
'react/react-in-jsx-scope': 'off',
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export default function RuntimeTestsExample() {
importTest: () => {
require('./tests/plugin/fileWorkletization.test');
require('./tests/plugin/contextObjects.test');
require('./tests/plugin/workletClasses.test');
},
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useEffect } from 'react';
import { View } from 'react-native';
import { useSharedValue, runOnUI } from 'react-native-reanimated';
import { render, wait, describe, getRegisteredValue, registerValue, test, expect } from '../../ReJest/RuntimeTestsApi';
import { getThree, implicitContextObject } from './fileWorkletization';
import { ImplicitWorkletClass, getThree, implicitContextObject } from './fileWorkletization';

const SHARED_VALUE_REF = 'SHARED_VALUE_REF';

Expand Down Expand Up @@ -44,4 +44,23 @@ describe('Test file workletization', () => {
const sharedValue = await getRegisteredValue(SHARED_VALUE_REF);
expect(sharedValue.onUI).toBe(5);
});

test('WorkletClasses are workletized', async () => {
const ExampleComponent = () => {
const output = useSharedValue<number | null>(null);
registerValue(SHARED_VALUE_REF, output);

useEffect(() => {
runOnUI(() => {
output.value = new ImplicitWorkletClass().getSeven();
})();
});

return <View />;
};
await render(<ExampleComponent />);
await wait(100);
const sharedValue = await getRegisteredValue(SHARED_VALUE_REF);
expect(sharedValue.onUI).toBe(7);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,13 @@ export const implicitContextObject = {
return this.getFour() + 1;
},
};

export class ImplicitWorkletClass {
getSix() {
return 6;
}

getSeven() {
return this.getSix() + 1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import React, { useEffect } from 'react';
import { View } from 'react-native';
import { useSharedValue, runOnUI } from 'react-native-reanimated';
import { render, wait, describe, getRegisteredValue, registerValue, test, expect } from '../../ReJest/RuntimeTestsApi';

const SHARED_VALUE_REF = 'SHARED_VALUE_REF';

class WorkletClass {
__workletClass = true;
value = 0;
getOne() {
return 1;
}

getTwo() {
return this.getOne() + 1;
}

getIncremented() {
return ++this.value;
}
}

describe('Test worklet classes', () => {
test('class works on React runtime', async () => {
const ExampleComponent = () => {
const output = useSharedValue<number | null>(null);
registerValue(SHARED_VALUE_REF, output);
const clazz = new WorkletClass();

output.value = clazz.getTwo() + clazz.getIncremented() + clazz.getIncremented();

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

test('constructor works on Worklet runtime', async () => {
const ExampleComponent = () => {
useEffect(() => {
runOnUI(() => {
const clazz = new WorkletClass();
clazz.getOne();
})();
});

return <View />;
};
await render(<ExampleComponent />);
await wait(100);
// TODO: assert no crash here
});

test('class methods work on Worklet runtime', async () => {
const ExampleComponent = () => {
const output = useSharedValue<number | null>(null);
registerValue(SHARED_VALUE_REF, output);

useEffect(() => {
runOnUI(() => {
const clazz = new WorkletClass();
output.value = clazz.getOne();
})();
});

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

test('class instance methods preserve binding', async () => {
const ExampleComponent = () => {
const output = useSharedValue<number | null>(null);
registerValue(SHARED_VALUE_REF, output);

useEffect(() => {
runOnUI(() => {
const clazz = new WorkletClass();
output.value = clazz.getTwo();
})();
});

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

test('class instances preserve state', async () => {
const ExampleComponent = () => {
const output = useSharedValue<number | null>(null);
registerValue(SHARED_VALUE_REF, output);

useEffect(() => {
runOnUI(() => {
const clazz = new WorkletClass();
output.value = clazz.getIncremented() + clazz.getIncremented();
})();
});

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

test('instanceof operator works on Worklet runtime', async () => {
const ExampleComponent = () => {
const output = useSharedValue<boolean | null>(null);
registerValue(SHARED_VALUE_REF, output);

useEffect(() => {
runOnUI(() => {
const clazz = new WorkletClass();
output.value = clazz instanceof WorkletClass;
})();
});

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

// TODO: Add a test that throws when class is sent from React to Worklet runtime.
});
Loading