From 8c88c1f18b68bf6cc1b8ddba206ab86acb20ba8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 23 Jul 2025 03:44:15 -0700 Subject: [PATCH 1/3] Honor ignored frames in errors reported by Fantom (#52765) Summary: Changelog: [internal] Reported locations for errors in Fantom is wrong, because it seems it's not ignoring "infra" frames. This was caused by the `stack` property in `ErrorWithCustomBlame` being set on the error objects and shadowing the getter that removes the necessary frames. This fixes that by forcing that property to be deleted. Reviewed By: christophpurrer Differential Revision: D78747119 --- private/react-native-fantom/runtime/expect.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/private/react-native-fantom/runtime/expect.js b/private/react-native-fantom/runtime/expect.js index 6d876ed59c37..5a465afa96de 100644 --- a/private/react-native-fantom/runtime/expect.js +++ b/private/react-native-fantom/runtime/expect.js @@ -24,6 +24,15 @@ class ErrorWithCustomBlame extends Error { #cachedProcessedStack: ?string; #customStack: ?string; + constructor(message?: string, options?: {cause?: mixed, ...}) { + super(message, options); + + // The Error constructor forces an own `stack` property that shadows our + // getter, so deleting it restores that behavior. + // $FlowExpectedError[incompatible-type] + delete this.stack; + } + blameToPreviousFrame(): this { this.#cachedProcessedStack = null; this.#ignoredFrameCount++; @@ -34,6 +43,10 @@ class ErrorWithCustomBlame extends Error { get stack(): string { if (this.#cachedProcessedStack == null) { const originalStack = this.#customStack ?? super.stack; + // Calling `super.stack` forces an own `stack` property that shadows our + // getter, so deleting it restores that behavior. + // $FlowExpectedError[incompatible-type] + delete this.stack; const lines = originalStack.split('\n'); const index = lines.findIndex(line => From 278a7c46188678a2dd8df4285213cfe47b88dc30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 23 Jul 2025 03:44:15 -0700 Subject: [PATCH 2/3] Create new environment variable to force running benchmarks in test mode (#52759) Summary: Changelog: [internal] This introduces a new environment variable for Fantom to disable benchmarks (`FANTOM_FORCE_TEST_MODE`), without having to run in CI mode. Reviewed By: rshest Differential Revision: D78672864 --- .../react-native-fantom/runner/EnvironmentOptions.js | 7 +++++++ .../react-native-fantom/runner/entrypoint-template.js | 6 +++--- private/react-native-fantom/runner/runner.js | 2 -- private/react-native-fantom/runner/utils.js | 10 ---------- private/react-native-fantom/src/Benchmark.js | 3 ++- private/react-native-fantom/src/Constants.js | 2 ++ 6 files changed, 14 insertions(+), 16 deletions(-) diff --git a/private/react-native-fantom/runner/EnvironmentOptions.js b/private/react-native-fantom/runner/EnvironmentOptions.js index 6ef811e02097..e8aef4cd6362 100644 --- a/private/react-native-fantom/runner/EnvironmentOptions.js +++ b/private/react-native-fantom/runner/EnvironmentOptions.js @@ -17,3 +17,10 @@ export const enableCppDebugging: boolean = Boolean( ); export const isOSS: boolean = Boolean(process.env.FANTOM_FORCE_OSS_BUILD); + +export const isCI: boolean = + Boolean(process.env.SANDCASTLE) || Boolean(process.env.GITHUB_ACTIONS); + +export const forceTestModeForBenchmarks: boolean = Boolean( + process.env.FANTOM_FORCE_TEST_MODE, +); diff --git a/private/react-native-fantom/runner/entrypoint-template.js b/private/react-native-fantom/runner/entrypoint-template.js index 5a760b6cd643..8ccca412fad8 100644 --- a/private/react-native-fantom/runner/entrypoint-template.js +++ b/private/react-native-fantom/runner/entrypoint-template.js @@ -11,6 +11,7 @@ import type {SnapshotConfig} from '../runtime/snapshotContext'; import type {FantomTestConfig} from './getFantomTestConfigs'; +import * as EnvironmentOptions from './EnvironmentOptions'; import formatFantomConfig from './formatFantomConfig'; module.exports = function entrypointTemplate({ @@ -19,14 +20,12 @@ module.exports = function entrypointTemplate({ featureFlagsModulePath, testConfig, snapshotConfig, - isRunningFromCI, }: { testPath: string, setupModulePath: string, featureFlagsModulePath: string, testConfig: FantomTestConfig, snapshotConfig: SnapshotConfig, - isRunningFromCI: boolean, }): string { return `/** * Copyright (c) Meta Platforms, Inc. and affiliates. @@ -66,7 +65,8 @@ ${ } setConstants({ - isRunningFromCI: ${String(isRunningFromCI)}, + isRunningFromCI: ${String(EnvironmentOptions.isCI)}, + forceTestModeForBenchmarks: ${String(EnvironmentOptions.forceTestModeForBenchmarks)}, fantomConfigSummary: '${formatFantomConfig(testConfig)}', }); diff --git a/private/react-native-fantom/runner/runner.js b/private/react-native-fantom/runner/runner.js index d184b1f9cffb..48587ce30004 100644 --- a/private/react-native-fantom/runner/runner.js +++ b/private/react-native-fantom/runner/runner.js @@ -32,7 +32,6 @@ import { getDebugInfoFromCommandResult, getHermesCompilerTarget, getShortHash, - isRunningFromCI, printConsoleLog, runBuck2, runBuck2Sync, @@ -273,7 +272,6 @@ module.exports = async function runTest( updateSnapshot: snapshotState._updateSnapshot, data: getInitialSnapshotData(snapshotState), }, - isRunningFromCI: isRunningFromCI(), }); const entrypointPath = path.join( diff --git a/private/react-native-fantom/runner/utils.js b/private/react-native-fantom/runner/utils.js index 0fbc80f70603..b840f7625cd8 100644 --- a/private/react-native-fantom/runner/utils.js +++ b/private/react-native-fantom/runner/utils.js @@ -101,16 +101,6 @@ export type SyncCommandResult = { stderr: string, }; -function isEmpty(value: ?string): boolean { - return value == null || value === ''; -} - -export function isRunningFromCI(): boolean { - return ( - !isEmpty(process.env.SANDCASTLE) || !isEmpty(process.env.GITHUB_ACTIONS) - ); -} - function maybeLogCommand(command: string, args: Array): void { if (EnvironmentOptions.logCommands) { console.log(`RUNNING \`${command} ${args.join(' ')}\``); diff --git a/private/react-native-fantom/src/Benchmark.js b/private/react-native-fantom/src/Benchmark.js index eead18ea58b6..34871751d5c5 100644 --- a/private/react-native-fantom/src/Benchmark.js +++ b/private/react-native-fantom/src/Benchmark.js @@ -61,7 +61,7 @@ export function suite( throw new Error('No benchmark tests defined'); } - const {isRunningFromCI} = getConstants(); + const {isRunningFromCI, forceTestModeForBenchmarks} = getConstants(); // If we're running from CI and there's no verification function, there's // no point in running the benchmark. @@ -69,6 +69,7 @@ export function suite( // logic in the benchmark doesn't break. const isTestOnly = suiteOptions.testOnly === true || + forceTestModeForBenchmarks || (isRunningFromCI && verifyFns.length === 0); const benchOptions: BenchOptions = isTestOnly diff --git a/private/react-native-fantom/src/Constants.js b/private/react-native-fantom/src/Constants.js index 4515eb5a17e7..21f79977420d 100644 --- a/private/react-native-fantom/src/Constants.js +++ b/private/react-native-fantom/src/Constants.js @@ -10,11 +10,13 @@ type FantomConstants = $ReadOnly<{ isRunningFromCI: boolean, + forceTestModeForBenchmarks: boolean, fantomConfigSummary: string, }>; let constants: FantomConstants = { isRunningFromCI: false, + forceTestModeForBenchmarks: false, fantomConfigSummary: '', }; From 2dc72bd07d5c5eea15118ea3fb794e43f723ea96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 23 Jul 2025 03:44:15 -0700 Subject: [PATCH 3/3] Add new environment variables to force CI and debug C++ (#52776) Summary: Changelog: [internal] `FANTOM_FORCE_CI_MODE` is just an explicit way to indicate that we're on CI, so we'd run benchmarks in test mode, for example. `FANTOM_DEBUG_CPP` is just an alias for `FANTOM_ENABLE_CPP_DEBUGGING` which is unnecessarily long. Differential Revision: D78801918 --- .../runner/EnvironmentOptions.js | 33 ++++++++++++++++--- private/react-native-fantom/runner/runner.js | 2 +- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/private/react-native-fantom/runner/EnvironmentOptions.js b/private/react-native-fantom/runner/EnvironmentOptions.js index e8aef4cd6362..decebd6e01b4 100644 --- a/private/react-native-fantom/runner/EnvironmentOptions.js +++ b/private/react-native-fantom/runner/EnvironmentOptions.js @@ -8,19 +8,44 @@ * @format */ +/** + * Prints the output of the Fantom tester to the test output. + */ export const printCLIOutput: boolean = Boolean(process.env.FANTOM_PRINT_OUTPUT); +/** + * Logs all external commands executed by the runner. + */ export const logCommands: boolean = Boolean(process.env.FANTOM_LOG_COMMANDS); -export const enableCppDebugging: boolean = Boolean( - process.env.FANTOM_ENABLE_CPP_DEBUGGING, -); +/** + * Enables the C++ debugger for the current test run. + */ +export const debugCpp: boolean = + Boolean(process.env.FANTOM_DEBUG_CPP) || + // Legacy + Boolean(process.env.FANTOM_ENABLE_CPP_DEBUGGING); +/** + * Indicates if the current test run is done in an OSS environment (as opposed + * to internal Meta infra). + */ export const isOSS: boolean = Boolean(process.env.FANTOM_FORCE_OSS_BUILD); +/** + * Indicates if the current test run is done in CI, which forces: + * 1. Prebuilding all binaries (Fantom tester and Hermes compiler). + * 2. Running benchmarks in test mode (see below). + */ export const isCI: boolean = - Boolean(process.env.SANDCASTLE) || Boolean(process.env.GITHUB_ACTIONS); + Boolean(process.env.FANTOM_FORCE_CI_MODE) || + Boolean(process.env.SANDCASTLE) || + Boolean(process.env.GITHUB_ACTIONS); +/** + * Forces benchmarks to run in test mode (running a single time to ensure + * correctness instead of multiples times to measure performance). + */ export const forceTestModeForBenchmarks: boolean = Boolean( process.env.FANTOM_FORCE_TEST_MODE, ); diff --git a/private/react-native-fantom/runner/runner.js b/private/react-native-fantom/runner/runner.js index 48587ce30004..6d1b3fde81a7 100644 --- a/private/react-native-fantom/runner/runner.js +++ b/private/react-native-fantom/runner/runner.js @@ -336,7 +336,7 @@ module.exports = async function runTest( ...rnTesterCommandArgs, ], { - withFDB: EnvironmentOptions.enableCppDebugging, + withFDB: EnvironmentOptions.debugCpp, }, );