Add flag to force running tests in optimized mode (#47870)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47870

Changelog: [internal]

This flag allows us to run optimized mode by using the right buck modes for the Fantom CLI, using minified + dev in Metro and building bytecode using Buck as well.

It's disabled by default but in the future we can enable it based on the configuration in the test file (e.g.: if it's a benchmark) or we can run tests in both modes by default to catch problems caused by the differences between environments.

Reviewed By: rshest

Differential Revision: D66292709

fbshipit-source-id: d25294b739ff6a67507990241784b838d5b30dcd
This commit is contained in:
Rubén Norte 2024-11-21 03:58:36 -08:00 committed by Facebook GitHub Bot
parent 550b0c0ed1
commit 92a476661c

View File

@ -23,6 +23,8 @@ import os from 'os';
import path from 'path'; import path from 'path';
const BUILD_OUTPUT_PATH = path.resolve(__dirname, '..', 'build'); const BUILD_OUTPUT_PATH = path.resolve(__dirname, '..', 'build');
const ENABLE_OPTIMIZED_MODE: false = false;
const PRINT_FANTOM_OUTPUT: false = false; const PRINT_FANTOM_OUTPUT: false = false;
function parseRNTesterCommandResult( function parseRNTesterCommandResult(
@ -59,15 +61,17 @@ function parseRNTesterCommandResult(
} }
function getBuckModeForPlatform() { function getBuckModeForPlatform() {
const mode = ENABLE_OPTIMIZED_MODE ? 'opt' : 'dev';
switch (os.platform()) { switch (os.platform()) {
case 'linux': case 'linux':
return '@//arvr/mode/linux/dev'; return `@//arvr/mode/linux/${mode}`;
case 'darwin': case 'darwin':
return os.arch() === 'arm64' return os.arch() === 'arm64'
? '@//arvr/mode/mac-arm/dev' ? `@//arvr/mode/mac-arm/${mode}`
: '@//arvr/mode/mac/dev'; : `@//arvr/mode/mac/${mode}`;
case 'win32': case 'win32':
return '@//arvr/mode/win/dev'; return `@//arvr/mode/win/${mode}`;
default: default:
throw new Error(`Unsupported platform: ${os.platform()}`); throw new Error(`Unsupported platform: ${os.platform()}`);
} }
@ -77,6 +81,55 @@ function getShortHash(contents: string): string {
return crypto.createHash('md5').update(contents).digest('hex').slice(0, 8); return crypto.createHash('md5').update(contents).digest('hex').slice(0, 8);
} }
function generateBytecodeBundle({
sourcePath,
bytecodePath,
}: {
sourcePath: string,
bytecodePath: string,
}): void {
const hermesCompilerCommandArgs = [
'run',
getBuckModeForPlatform(),
'//xplat/hermes/tools/hermesc:hermesc',
'--',
'-emit-binary',
'-O',
'-max-diagnostic-width',
'80',
'-out',
bytecodePath,
sourcePath,
];
const hermesCompilerCommandResult = spawnSync(
'buck2',
hermesCompilerCommandArgs,
{
encoding: 'utf8',
env: {
...process.env,
PATH: `/usr/local/bin:${process.env.PATH ?? ''}`,
},
},
);
if (hermesCompilerCommandResult.status !== 0) {
throw new Error(
[
'Failed to run Hermes compiler. Full output:',
'buck2 ' + hermesCompilerCommandArgs.join(' '),
'stdout:',
hermesCompilerCommandResult.stdout,
'stderr:',
hermesCompilerCommandResult.stderr,
'error:',
hermesCompilerCommandResult.error,
].join('\n'),
);
}
}
module.exports = async function runTest( module.exports = async function runTest(
globalConfig: {...}, globalConfig: {...},
config: {...}, config: {...},
@ -86,6 +139,8 @@ module.exports = async function runTest(
): mixed { ): mixed {
const startTime = Date.now(); const startTime = Date.now();
const isOptimizedMode = ENABLE_OPTIMIZED_MODE;
const metroConfig = await Metro.loadConfig({ const metroConfig = await Metro.loadConfig({
config: path.resolve(__dirname, '..', 'config', 'metro.config.js'), config: path.resolve(__dirname, '..', 'config', 'metro.config.js'),
}); });
@ -102,24 +157,34 @@ module.exports = async function runTest(
`${getShortHash(entrypointContents)}-${path.basename(testPath)}`, `${getShortHash(entrypointContents)}-${path.basename(testPath)}`,
); );
const testBundlePath = entrypointPath + '.bundle'; const testBundlePath = entrypointPath + '.bundle';
const testJSBundlePath = testBundlePath + '.js';
const testBytecodeBundlePath = testJSBundlePath + '.hbc';
fs.mkdirSync(path.dirname(entrypointPath), {recursive: true}); fs.mkdirSync(path.dirname(entrypointPath), {recursive: true});
fs.writeFileSync(entrypointPath, entrypointContents, 'utf8'); fs.writeFileSync(entrypointPath, entrypointContents, 'utf8');
await Metro.runBuild(metroConfig, { await Metro.runBuild(metroConfig, {
entry: entrypointPath, entry: entrypointPath,
out: testBundlePath, out: testJSBundlePath,
platform: 'android', platform: 'android',
minify: false, minify: isOptimizedMode,
dev: true, dev: !isOptimizedMode,
}); });
if (isOptimizedMode) {
generateBytecodeBundle({
sourcePath: testJSBundlePath,
bytecodePath: testBytecodeBundlePath,
});
}
const rnTesterCommandArgs = [ const rnTesterCommandArgs = [
'run', 'run',
getBuckModeForPlatform(), getBuckModeForPlatform(),
'//xplat/ReactNative/react-native-cxx/samples/tester:tester', '//xplat/ReactNative/react-native-cxx/samples/tester:tester',
'--', '--',
`--bundlePath=${testBundlePath}`, '--bundlePath',
testBundlePath,
]; ];
const rnTesterCommandResult = spawnSync('buck2', rnTesterCommandArgs, { const rnTesterCommandResult = spawnSync('buck2', rnTesterCommandArgs, {
encoding: 'utf8', encoding: 'utf8',