/
githubmr
/
facebook-react
Обзор
Документация
Войти
/
githubmr
/
facebook-react
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
main
compiler/packages/babel-plugin-react-compiler/src/Utils/TestUtils.ts
225 строк
6 KB
Sebastian "Sebbie" Silbermann
[compiler] Export `PluginOptions` as a type that can be used in input positions (#34550)
22 сен 2025, 19:28
Не верифицирован
22 сен 2025, 19:28
720bb13
Код
Авторство
О чём код?
/** * 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. */ import {fromZodError} from 'zod-validation-error'; import {CompilerError} from '../CompilerError'; import { CompilationMode, defaultOptions, parsePluginOptions, PluginOptions, } from '../Entrypoint'; import {EnvironmentConfig} from '..'; import { EnvironmentConfigSchema, PartialEnvironmentConfig, } from '../HIR/Environment'; import {Err, Ok, Result} from './Result'; import {hasOwnProperty} from './utils'; function tryParseTestPragmaValue(val: string): Result<unknown, unknown> { try { let parsedVal: unknown; const stringMatch = /^"([^"]*)"$/.exec(val); if (stringMatch && stringMatch.length > 1) { parsedVal = stringMatch[1]; } else { parsedVal = JSON.parse(val); } return Ok(parsedVal); } catch (e) { return Err(e); } } const testComplexConfigDefaults: PartialEnvironmentConfig = { validateNoCapitalizedCalls: [], enableChangeDetectionForDebugging: { source: 'react-compiler-runtime', importSpecifierName: '$structuralCheck', }, enableEmitFreeze: { source: 'react-compiler-runtime', importSpecifierName: 'makeReadOnly', }, enableEmitInstrumentForget: { fn: { source: 'react-compiler-runtime', importSpecifierName: 'useRenderCounter', }, gating: { source: 'react-compiler-runtime', importSpecifierName: 'shouldInstrument', }, globalGating: 'DEV', }, enableEmitHookGuards: { source: 'react-compiler-runtime', importSpecifierName: '$dispatcherGuard', }, inlineJsxTransform: { elementSymbol: 'react.transitional.element', globalDevVar: 'DEV', }, lowerContextAccess: { source: 'react-compiler-runtime', importSpecifierName: 'useContext_withSelector', }, inferEffectDependencies: [ { function: { source: 'react', importSpecifierName: 'useEffect', }, autodepsIndex: 1, }, { function: { source: 'shared-runtime', importSpecifierName: 'useSpecialEffect', }, autodepsIndex: 2, }, { function: { source: 'useEffectWrapper', importSpecifierName: 'default', }, autodepsIndex: 1, }, ], }; function* splitPragma( pragma: string, ): Generator<{key: string; value: string | null}> { for (const entry of pragma.split('@')) { const keyVal = entry.trim(); const valIdx = keyVal.indexOf(':'); if (valIdx === -1) { yield {key: keyVal.split(' ', 1)[0], value: null}; } else { yield {key: keyVal.slice(0, valIdx), value: keyVal.slice(valIdx + 1)}; } } } /** * For snap test fixtures and playground only. */ function parseConfigPragmaEnvironmentForTest( pragma: string, defaultConfig: PartialEnvironmentConfig, ): EnvironmentConfig { // throw early if the defaults are invalid EnvironmentConfigSchema.parse(defaultConfig); const maybeConfig: Partial<Record<keyof EnvironmentConfig, unknown>> = defaultConfig; for (const {key, value: val} of splitPragma(pragma)) { if (!hasOwnProperty(EnvironmentConfigSchema.shape, key)) { continue; } const isSet = val == null || val === 'true'; if (isSet && key in testComplexConfigDefaults) { maybeConfig[key] = testComplexConfigDefaults[key]; } else if (isSet) { maybeConfig[key] = true; } else if (val === 'false') { maybeConfig[key] = false; } else if (val) { const parsedVal = tryParseTestPragmaValue(val).unwrap(); if (key === 'customMacros' && typeof parsedVal === 'string') { const valSplit = parsedVal.split('.'); const props = []; for (const elt of valSplit.slice(1)) { if (elt === '*') { props.push({type: 'wildcard'}); } else if (elt.length > 0) { props.push({type: 'name', name: elt}); } } maybeConfig[key] = [[valSplit[0], props]]; continue; } maybeConfig[key] = parsedVal; } } const config = EnvironmentConfigSchema.safeParse(maybeConfig); if (config.success) { /** * Unless explicitly enabled, do not insert HMR handling code * in test fixtures or playground to reduce visual noise. */ if (config.data.enableResetCacheOnSourceFileChanges == null) { config.data.enableResetCacheOnSourceFileChanges = false; } return config.data; } CompilerError.invariant(false, { reason: 'Internal error, could not parse config from pragma string', description: `${fromZodError(config.error)}`, details: [ { kind: 'error', loc: null, message: null, }, ], suggestions: null, }); } const testComplexPluginOptionDefaults: PluginOptions = { gating: { source: 'ReactForgetFeatureFlag', importSpecifierName: 'isForgetEnabled_Fixtures', }, }; export function parseConfigPragmaForTests( pragma: string, defaults: { compilationMode: CompilationMode; environment?: PartialEnvironmentConfig; }, ): PluginOptions { const environment = parseConfigPragmaEnvironmentForTest( pragma, defaults.environment ?? {}, ); const options: Record<keyof PluginOptions, unknown> = { ...defaultOptions, panicThreshold: 'all_errors', compilationMode: defaults.compilationMode, environment, }; for (const {key, value: val} of splitPragma(pragma)) { if (!hasOwnProperty(defaultOptions, key)) { continue; } const isSet = val == null || val === 'true'; if (isSet && key in testComplexPluginOptionDefaults) { options[key] = testComplexPluginOptionDefaults[key]; } else if (isSet) { options[key] = true; } else if (val === 'false') { options[key] = false; } else if (val != null) { const parsedVal = tryParseTestPragmaValue(val).unwrap(); if (key === 'target' && parsedVal === 'donotuse_meta_internal') { options[key] = { kind: parsedVal, runtimeModule: 'react', }; } else { options[key] = parsedVal; } } } return parsePluginOptions(options); }