From 131361d8fa212731da0728ffc18477b3b840d883 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Mon, 16 Dec 2024 03:12:28 -0800 Subject: [PATCH 1/2] Create TurboModule for test helpers (#48283) Summary: Migrate from custom JSI integration to use TurboModule base-class. This doesn't use codegen right now for ease of migration, and to avoid needing to setup a js_library buck definition for react-native-fantom. We should also figure out what the right abstraction/division of responsibilities is going forward for TesterAppDelegate and FantomModule. Changelog: [Internal] Reviewed By: rubennorte Differential Revision: D67111850 --- .../src/getFantomRenderedOutput.js | 17 ++++------- packages/react-native-fantom/src/index.js | 13 ++++----- .../src/specs/NativeFantomModule.js | 29 +++++++++++++++++++ 3 files changed, 40 insertions(+), 19 deletions(-) create mode 100644 packages/react-native-fantom/src/specs/NativeFantomModule.js diff --git a/packages/react-native-fantom/src/getFantomRenderedOutput.js b/packages/react-native-fantom/src/getFantomRenderedOutput.js index 7ae8677e39f8a2..496a462a3d3285 100644 --- a/packages/react-native-fantom/src/getFantomRenderedOutput.js +++ b/packages/react-native-fantom/src/getFantomRenderedOutput.js @@ -9,6 +9,7 @@ * @oncall react_native */ +import FantomModule from './specs/NativeFantomModule'; // $FlowExpectedError[untyped-import] import micromatch from 'micromatch'; import * as React from 'react'; @@ -19,12 +20,6 @@ export type RenderOutputConfig = { includeLayoutMetrics?: boolean, }; -// match RenderFormatOptions.h -type NativeRenderFormatOptions = { - includeRoot: boolean, - includeLayoutMetrics: boolean, -}; - type FantomJsonObject = { type: string, props: {[key: string]: string}, @@ -117,14 +112,12 @@ export default function getFantomRenderedOutput( includeLayoutMetrics = false, ...fantomConfig } = config; - const nativeConfig: NativeRenderFormatOptions = { - includeRoot, - includeLayoutMetrics, - }; - return new FantomRenderedOutput( JSON.parse( - global.$$JSTesterModuleName$$.getRenderedOutput(surfaceId, nativeConfig), + FantomModule.getRenderedOutput(surfaceId, { + includeRoot, + includeLayoutMetrics, + }), ), fantomConfig, ); diff --git a/packages/react-native-fantom/src/index.js b/packages/react-native-fantom/src/index.js index 0c3b79f7dbcd3b..fce55d5cbb6785 100644 --- a/packages/react-native-fantom/src/index.js +++ b/packages/react-native-fantom/src/index.js @@ -15,6 +15,7 @@ import type { import type {MixedElement} from 'react'; import getFantomRenderedOutput from './getFantomRenderedOutput'; +import FantomModule from './specs/NativeFantomModule'; import ReactFabric from 'react-native/Libraries/Renderer/shims/ReactFabric'; let globalSurfaceIdCounter = 1; @@ -34,7 +35,7 @@ class Root { render(element: MixedElement) { if (!this.#hasRendered) { - global.$$JSTesterModuleName$$.startSurface(this.#surfaceId); + FantomModule.startSurface(this.#surfaceId); this.#hasRendered = true; } @@ -42,15 +43,13 @@ class Root { } getMountingLogs(): Array { - return global.$$JSTesterModuleName$$.getMountingManagerLogs( - this.#surfaceId, - ); + return FantomModule.getMountingManagerLogs(this.#surfaceId); } destroy() { // TODO: check for leaks. - global.$$JSTesterModuleName$$.stopSurface(this.#surfaceId); - global.$$JSTesterModuleName$$.flushMessageQueue(); + FantomModule.stopSurface(this.#surfaceId); + FantomModule.flushMessageQueue(); } getRenderedOutput(config: RenderOutputConfig = {}): FantomRenderedOutput { @@ -81,7 +80,7 @@ export function runTask(task: () => void | Promise) { try { flushingQueue = true; - global.$$JSTesterModuleName$$.flushMessageQueue(); + FantomModule.flushMessageQueue(); } finally { flushingQueue = false; } diff --git a/packages/react-native-fantom/src/specs/NativeFantomModule.js b/packages/react-native-fantom/src/specs/NativeFantomModule.js new file mode 100644 index 00000000000000..da67f38a1e759a --- /dev/null +++ b/packages/react-native-fantom/src/specs/NativeFantomModule.js @@ -0,0 +1,29 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; + +import {TurboModuleRegistry} from 'react-native'; + +// match RenderFormatOptions.h +export type RenderFormatOptions = { + includeRoot: boolean, + includeLayoutMetrics: boolean, +}; + +interface Spec extends TurboModule { + startSurface: (surfaceId: number) => void; + stopSurface: (surfaceId: number) => void; + getMountingManagerLogs: (surfaceId: number) => Array; + flushMessageQueue: () => void; + getRenderedOutput: (surfaceId: number, config: RenderFormatOptions) => string; +} + +export default TurboModuleRegistry.getEnforcing('Fantom') as Spec; From 23a336a79b0bb43b3c53ac0c5f7f050e8924a54a Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Mon, 16 Dec 2024 03:12:28 -0800 Subject: [PATCH 2/2] Fix MacOS build Summary: Changelog: [Internal] Reviewed By: rubennorte Differential Revision: D67275514 --- packages/react-native-fantom/runner/runner.js | 8 ++++--- packages/react-native-fantom/runner/utils.js | 21 +++++++++++++------ .../runner/warmup/warmup.js | 6 +++--- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/packages/react-native-fantom/runner/runner.js b/packages/react-native-fantom/runner/runner.js index 99628faabe0a77..6ba49135c259d6 100644 --- a/packages/react-native-fantom/runner/runner.js +++ b/packages/react-native-fantom/runner/runner.js @@ -19,7 +19,7 @@ import { updateSnapshotsAndGetJestSnapshotResult, } from './snapshotUtils'; import { - getBuckModeForPlatform, + getBuckModesForPlatform, getDebugInfoFromCommandResult, getShortHash, runBuck2, @@ -76,7 +76,7 @@ function generateBytecodeBundle({ const hermesCompilerCommandResult = runBuck2( [ 'run', - getBuckModeForPlatform(isOptimizedMode), + ...getBuckModesForPlatform(isOptimizedMode), '//xplat/hermes/tools/hermesc:hermesc', '--', '-emit-binary', @@ -178,7 +178,9 @@ module.exports = async function runTest( const rnTesterCommandResult = runBuck2([ 'run', - getBuckModeForPlatform(testConfig.mode === FantomTestConfigMode.Optimized), + ...getBuckModesForPlatform( + testConfig.mode === FantomTestConfigMode.Optimized, + ), '//xplat/ReactNative/react-native-cxx/samples/tester:tester', '--', '--bundlePath', diff --git a/packages/react-native-fantom/runner/utils.js b/packages/react-native-fantom/runner/utils.js index 5d698977064d86..d5aa6deeac7ab3 100644 --- a/packages/react-native-fantom/runner/utils.js +++ b/packages/react-native-fantom/runner/utils.js @@ -18,21 +18,30 @@ import {SourceMapConsumer} from 'source-map'; const BUCK_ISOLATION_DIR = 'react-native-fantom-buck-out'; -export function getBuckModeForPlatform(enableRelease: boolean = false): string { +export function getBuckModesForPlatform( + enableRelease: boolean = false, +): $ReadOnlyArray { const mode = enableRelease ? 'opt' : 'dev'; + let osPlatform; switch (os.platform()) { case 'linux': - return `@//arvr/mode/linux/${mode}`; + osPlatform = `@//arvr/mode/linux/${mode}`; + break; case 'darwin': - return os.arch() === 'arm64' - ? `@//arvr/mode/mac-arm/${mode}` - : `@//arvr/mode/mac/${mode}`; + osPlatform = + os.arch() === 'arm64' + ? `@//arvr/mode/mac-arm/${mode}` + : `@//arvr/mode/mac/${mode}`; + break; case 'win32': - return `@//arvr/mode/win/${mode}`; + osPlatform = `@//arvr/mode/win/${mode}`; + break; default: throw new Error(`Unsupported platform: ${os.platform()}`); } + + return ['@//xplat/mode/react-force-cxx-platform', osPlatform]; } type SpawnResultWithOriginalCommand = { diff --git a/packages/react-native-fantom/runner/warmup/warmup.js b/packages/react-native-fantom/runner/warmup/warmup.js index ece60df0dc20c0..a5503c154ad0de 100644 --- a/packages/react-native-fantom/runner/warmup/warmup.js +++ b/packages/react-native-fantom/runner/warmup/warmup.js @@ -10,7 +10,7 @@ */ import { - getBuckModeForPlatform, + getBuckModesForPlatform, getDebugInfoFromCommandResult, runBuck2, } from '../utils'; @@ -96,7 +96,7 @@ async function warmUpMetro(isOptimizedMode: boolean): Promise { function warmUpHermesCompiler(isOptimizedMode: boolean): void { const buildHermesCompilerCommandResult = runBuck2([ 'build', - getBuckModeForPlatform(isOptimizedMode), + ...getBuckModesForPlatform(isOptimizedMode), '//xplat/hermes/tools/hermesc:hermesc', ]); @@ -110,7 +110,7 @@ function warmUpHermesCompiler(isOptimizedMode: boolean): void { function warmUpRNTesterCLI(isOptimizedMode: boolean): void { const buildRNTesterCommandResult = runBuck2([ 'build', - getBuckModeForPlatform(isOptimizedMode), + ...getBuckModesForPlatform(isOptimizedMode), '//xplat/ReactNative/react-native-cxx/samples/tester:tester', ]);