From 4a5669b63e1737477cee64e6dff7619bbd084393 Mon Sep 17 00:00:00 2001 From: Christoph Purrer Date: Thu, 20 Aug 2026 13:26:14 -0700 Subject: [PATCH] Align SampleTurboModuleExample UI with NativeCxxModuleExampleExample (#57985) Summary: The two RNTester TurboModule example screens had drifted apart, making it hard to compare TurboModule and C++ TurboModule behaviour side by side. Align `SampleTurboModuleExample` with the style already used by `NativeCxxModuleExampleExample`: - Order and group the entries in `_tests` the same way (callback, ArrayBuffer group, `get*` group, promises, `voidFunc`), so the buttons render in the same order on both screens. - Make the `Examples` union match the tests that actually exist; it still listed many entries copied from the C++ example that `SampleTurboModule` does not implement (`getCustomHostObject`, `getSet`, `setMenuItem`, ...) and was missing `getEnum`, `getRootTag` and `getUnsafeObject`. - Add the missing `installJSIBindings` entry to `ErrorExamples` and type `_renderResult` as `Examples | ErrorExamples`. - Surface rejected promises from the error tests in the UI instead of only logging them to the console, matching the other screen. - Fix `getUnsafeObject` to call `getUnsafeObject` instead of `getObject`. - Merge the duplicated `NativeSampleTurboModule` imports and drop a stale Flow suppression. Changelog: [Internal] Reviewed By: cipolleschi Differential Revision: D116375214 --- .../TurboModule/SampleTurboModuleExample.js | 90 ++++++++----------- 1 file changed, 39 insertions(+), 51 deletions(-) diff --git a/packages/rn-tester/js/examples/TurboModule/SampleTurboModuleExample.js b/packages/rn-tester/js/examples/TurboModule/SampleTurboModuleExample.js index aab25aacd46..ddfcc31fb04 100644 --- a/packages/rn-tester/js/examples/TurboModule/SampleTurboModuleExample.js +++ b/packages/rn-tester/js/examples/TurboModule/SampleTurboModuleExample.js @@ -14,8 +14,9 @@ import RNTesterText from '../../components/RNTesterText'; import styles from './TurboModuleExampleCommon'; import * as React from 'react'; import {FlatList, RootTagContext, TouchableOpacity, View} from 'react-native'; -import NativeSampleTurboModule from 'react-native/Libraries/TurboModule/samples/NativeSampleTurboModule'; -import {EnumInt} from 'react-native/Libraries/TurboModule/samples/NativeSampleTurboModule'; +import NativeSampleTurboModule, { + EnumInt, +} from 'react-native/Libraries/TurboModule/samples/NativeSampleTurboModule'; type State = { testResults: { @@ -33,6 +34,7 @@ type Examples = | 'getArray' | 'getBool' | 'getConstants' + | 'getEnum' | 'getCustomEnum' | 'getCustomHostObject' | 'getBinaryTreeNode' @@ -42,9 +44,11 @@ type Examples = | 'getMap' | 'getNumber' | 'getObject' + | 'getRootTag' | 'getSet' | 'getString' | 'getUnion' + | 'getUnsafeObject' | 'getValue' | 'getArrayBuffer' | 'createNativeBuffer' @@ -62,7 +66,8 @@ type ErrorExamples = | 'promiseThrows' | 'voidFuncAssert' | 'getObjectAssert' - | 'promiseAssert'; + | 'promiseAssert' + | 'installJSIBindings'; class SampleTurboModuleExample extends React.Component<{}, State> { static contextType: React.Context = RootTagContext; @@ -79,38 +84,12 @@ class SampleTurboModuleExample extends React.Component<{}, State> { NativeSampleTurboModule.getValueWithCallback(callbackValue => this._setResult('callback', callbackValue), ), - promise: () => - NativeSampleTurboModule.getValueWithPromise(false).then(valuePromise => - this._setResult('promise', valuePromise), - ), - rejectPromise: () => - NativeSampleTurboModule.getValueWithPromise(true) - .then(() => {}) - .catch(e => { - this._setResult('rejectPromise', e.message); - }), - getConstants: () => NativeSampleTurboModule.getConstants(), - voidFunc: () => NativeSampleTurboModule.voidFunc(), - getBool: () => NativeSampleTurboModule.getBool(true), - getEnum: () => - NativeSampleTurboModule.getEnum - ? NativeSampleTurboModule.getEnum(EnumInt.A) - : null, - getNumber: () => NativeSampleTurboModule.getNumber(99.95), - getString: () => NativeSampleTurboModule.getString('Hello'), getArray: () => NativeSampleTurboModule.getArray([ {a: 1, b: 'foo'}, {a: 2, b: 'bar'}, null, ]), - getObject: () => - NativeSampleTurboModule.getObject({a: 1, b: 'foo', c: null}), - getUnsafeObject: () => - NativeSampleTurboModule.getObject({a: 1, b: 'foo', c: null}), - getRootTag: () => NativeSampleTurboModule.getRootTag(this.context), - getValue: () => - NativeSampleTurboModule.getValue(5, 'test', {a: 1, b: 'foo'}), getArrayBuffer: () => { const input = new Uint8Array([1, 2, 3, 4]); const result = NativeSampleTurboModule.getArrayBuffer(input.buffer); @@ -130,6 +109,30 @@ class SampleTurboModuleExample extends React.Component<{}, State> { NativeSampleTurboModule.processAsyncBuffer( new Uint8Array([1, 2, 3]).buffer, ).then(length => this._setResult('processAsyncBuffer', length)), + getBool: () => NativeSampleTurboModule.getBool(true), + getConstants: () => NativeSampleTurboModule.getConstants(), + getEnum: () => + NativeSampleTurboModule.getEnum + ? NativeSampleTurboModule.getEnum(EnumInt.A) + : null, + getNumber: () => NativeSampleTurboModule.getNumber(99.95), + getObject: () => + NativeSampleTurboModule.getObject({a: 1, b: 'foo', c: null}), + getRootTag: () => NativeSampleTurboModule.getRootTag(this.context), + getString: () => NativeSampleTurboModule.getString('Hello'), + getUnsafeObject: () => + NativeSampleTurboModule.getUnsafeObject({a: 1, b: 'foo', c: null}), + getValue: () => + NativeSampleTurboModule.getValue(5, 'test', {a: 1, b: 'foo'}), + promise: () => + NativeSampleTurboModule.getValueWithPromise(false).then(valuePromise => + this._setResult('promise', valuePromise), + ), + rejectPromise: () => + NativeSampleTurboModule.getValueWithPromise(true) + .then(() => {}) + .catch(e => this._setResult('rejectPromise', e.message)), + voidFunc: () => NativeSampleTurboModule.voidFunc(), }; // $FlowFixMe[missing-local-annot] @@ -138,7 +141,6 @@ class SampleTurboModuleExample extends React.Component<{}, State> { try { NativeSampleTurboModule.voidFuncThrows?.(); } catch (e) { - console.error(e); return e.message; } }, @@ -146,22 +148,17 @@ class SampleTurboModuleExample extends React.Component<{}, State> { try { NativeSampleTurboModule.getObjectThrows?.({a: 1, b: 'foo', c: null}); } catch (e) { - console.error(e); return e.message; } }, - promiseThrows: () => { + promiseThrows: () => NativeSampleTurboModule.promiseThrows?.() .then(() => {}) - .catch(e => { - console.error(e); - }); - }, + .catch(e => this._setResult('promiseThrows', e.message)), voidFuncAssert: () => { try { NativeSampleTurboModule.voidFuncAssert?.(); } catch (e) { - console.error(e); return e.message; } }, @@ -169,20 +166,14 @@ class SampleTurboModuleExample extends React.Component<{}, State> { try { NativeSampleTurboModule.getObjectAssert?.({a: 1, b: 'foo', c: null}); } catch (e) { - console.error(e); return e.message; } }, - promiseAssert: () => { + promiseAssert: () => NativeSampleTurboModule.promiseAssert?.() .then(() => {}) - .catch(e => { - console.error(e); - }); - }, - installJSIBindings: () => { - return global.__SampleTurboModuleJSIBindings; - }, + .catch(e => this._setResult('promiseAssert', e.message)), + installJSIBindings: () => global.__SampleTurboModuleJSIBindings, }; _setResult( @@ -199,9 +190,6 @@ class SampleTurboModuleExample extends React.Component<{}, State> { | Array<$FlowFixMe>, ) { this.setState(({testResults}) => ({ - /* $FlowFixMe[cannot-spread-indexer] (>=0.122.0 site=react_native_fb) - * This comment suppresses an error found when Flow v0.122.0 was - * deployed. To see the error, delete this comment and run Flow. */ testResults: { ...testResults, /* $FlowFixMe[invalid-computed-prop] (>=0.111.0 site=react_native_fb) @@ -212,7 +200,7 @@ class SampleTurboModuleExample extends React.Component<{}, State> { })); } - _renderResult(name: string): React.Node { + _renderResult(name: Examples | ErrorExamples): React.Node { const result = this.state.testResults[name] || {}; return ( @@ -277,7 +265,7 @@ class SampleTurboModuleExample extends React.Component<{}, State> { ) }> - Run all tests + Run function call tests