diff --git a/packages/react-native-fantom/runner/entrypoint-template.js b/packages/react-native-fantom/runner/entrypoint-template.js index 8d53f6b27a942d..5a760b6cd64327 100644 --- a/packages/react-native-fantom/runner/entrypoint-template.js +++ b/packages/react-native-fantom/runner/entrypoint-template.js @@ -40,7 +40,8 @@ module.exports = function entrypointTemplate({ */ import {registerTest} from '${setupModulePath}'; -import {setConstants} from '@react-native/fantom'; +import {setConstants} from '@react-native/fantom/src/Constants'; + ${ Object.keys(testConfig.flags.jsOnly).length > 0 ? `import * as ReactNativeFeatureFlags from '${featureFlagsModulePath}'; diff --git a/packages/react-native-fantom/runtime/patchWeakRef.js b/packages/react-native-fantom/runtime/patchWeakRef.js index 39aada1f760289..63a6842e63ba82 100644 --- a/packages/react-native-fantom/runtime/patchWeakRef.js +++ b/packages/react-native-fantom/runtime/patchWeakRef.js @@ -8,8 +8,6 @@ * @format */ -import * as Fantom from '@react-native/fantom'; - let initialized = false; /** @@ -31,6 +29,9 @@ export default function patchWeakRef(): void { // $FlowExpectedError[cannot-write] WeakRef.prototype.deref = function patchedDeref(this: WeakRef): T { + // Lazily require the module to avoid loading it before the test logic. + const Fantom = require('@react-native/fantom'); + if (!Fantom.isInWorkLoop()) { throw new Error( 'Unexpected call to `WeakRef.deref()` outside of the Event Loop. Please use this method within `Fantom.runTask()`.', @@ -43,6 +44,9 @@ export default function patchWeakRef(): void { const OriginalWeakRef = WeakRef; global.WeakRef = function WeakRef(...args) { + // Lazily require the module to avoid loading it before the test logic. + const Fantom = require('@react-native/fantom'); + if (!Fantom.isInWorkLoop()) { throw new Error( 'Unexpected instantiation of `WeakRef` outside of the Event Loop. Please create the instance within `Fantom.runTask()`.', diff --git a/packages/react-native-fantom/runtime/setup.js b/packages/react-native-fantom/runtime/setup.js index b7d724a61b959d..896d15a5fe4968 100644 --- a/packages/react-native-fantom/runtime/setup.js +++ b/packages/react-native-fantom/runtime/setup.js @@ -14,7 +14,6 @@ import expect from './expect'; import {createMockFunction} from './mocks'; import patchWeakRef from './patchWeakRef'; import {setupSnapshotConfig, snapshotContext} from './snapshotContext'; -import NativeFantom from 'react-native/src/private/testing/fantom/specs/NativeFantom'; export type TestCaseResult = { ancestorTitles: Array, @@ -380,6 +379,10 @@ function runSuite(suite: Suite): TestCaseResult[] { } function reportTestSuiteResult(testSuiteResult: TestSuiteResult): void { + // Force the import of the native module to be lazy + const NativeFantom = + require('react-native/src/private/testing/fantom/specs/NativeFantom').default; + NativeFantom.reportTestSuiteResultsJSON( JSON.stringify({ type: 'test-result', @@ -389,6 +392,10 @@ function reportTestSuiteResult(testSuiteResult: TestSuiteResult): void { } function validateEmptyMessageQueue(): void { + // Force the import of the native module to be lazy + const NativeFantom = + require('react-native/src/private/testing/fantom/specs/NativeFantom').default; + NativeFantom.validateEmptyMessageQueue(); } diff --git a/packages/react-native-fantom/src/Constants.js b/packages/react-native-fantom/src/Constants.js new file mode 100644 index 00000000000000..4515eb5a17e733 --- /dev/null +++ b/packages/react-native-fantom/src/Constants.js @@ -0,0 +1,27 @@ +/** + * 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 + */ + +type FantomConstants = $ReadOnly<{ + isRunningFromCI: boolean, + fantomConfigSummary: string, +}>; + +let constants: FantomConstants = { + isRunningFromCI: false, + fantomConfigSummary: '', +}; + +export function getConstants(): FantomConstants { + return constants; +} + +export function setConstants(newConstants: FantomConstants): void { + constants = newConstants; +} diff --git a/packages/react-native-fantom/src/__tests__/FantomModuleInit-itest.js b/packages/react-native-fantom/src/__tests__/FantomModuleInit-itest.js new file mode 100644 index 00000000000000..a5b5ef91038c59 --- /dev/null +++ b/packages/react-native-fantom/src/__tests__/FantomModuleInit-itest.js @@ -0,0 +1,21 @@ +/** + * 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 + */ + +describe('FantomModuleInit', () => { + it('should not load the Fantom module eagerly', () => { + expect(global.__FANTOM_PACKAGE_LOADED__).toBeUndefined(); + }); + + it('should load the Fantom module lazily', () => { + require('@react-native/fantom'); + + expect(global.__FANTOM_PACKAGE_LOADED__).toBe(true); + }); +}); diff --git a/packages/react-native-fantom/src/index.js b/packages/react-native-fantom/src/index.js index 18a122bf850702..1dd864d1309be1 100644 --- a/packages/react-native-fantom/src/index.js +++ b/packages/react-native-fantom/src/index.js @@ -18,6 +18,7 @@ import type ReactNativeDocument from 'react-native/src/private/webapis/dom/nodes import ReactNativeElement from '../../react-native/src/private/webapis/dom/nodes/ReadOnlyNode'; import * as Benchmark from './Benchmark'; +import {getConstants} from './Constants'; import getFantomRenderedOutput from './getFantomRenderedOutput'; import {LogBox} from 'react-native'; import {createRootTag} from 'react-native/Libraries/ReactNative/RootTag'; @@ -38,6 +39,8 @@ export type RootConfig = { devicePixelRatio?: number, }; +export {getConstants} from './Constants'; + // Defaults use iPhone 14 values (very common device). const DEFAULT_VIEWPORT_WIDTH = 390; const DEFAULT_VIEWPORT_HEIGHT = 844; @@ -520,24 +523,6 @@ export function enqueueModalSizeUpdate( export const unstable_benchmark = Benchmark; -type FantomConstants = $ReadOnly<{ - isRunningFromCI: boolean, - fantomConfigSummary: string, -}>; - -let constants: FantomConstants = { - isRunningFromCI: false, - fantomConfigSummary: '', -}; - -export function getConstants(): FantomConstants { - return constants; -} - -export function setConstants(newConstants: FantomConstants): void { - constants = newConstants; -} - /** * Quick and dirty polyfills required by tinybench. */ @@ -662,3 +647,5 @@ function runLogBoxCheck() { throw new Error(message); } } + +global.__FANTOM_PACKAGE_LOADED__ = true;