Compare commits
1 Commits
component-
...
pr32012
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b817b78bc |
@@ -0,0 +1,13 @@
|
|||||||
|
import { c as _c } from "react/compiler-runtime"; //
|
||||||
|
@compilationMode(all)
|
||||||
|
function nonReactFn() {
|
||||||
|
const $ = _c(1);
|
||||||
|
let t0;
|
||||||
|
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||||
|
t0 = {};
|
||||||
|
$[0] = t0;
|
||||||
|
} else {
|
||||||
|
t0 = $[0];
|
||||||
|
}
|
||||||
|
return t0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// @compilationMode(infer)
|
||||||
|
function nonReactFn() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
@@ -79,6 +79,24 @@ function Foo() {
|
|||||||
// @flow
|
// @flow
|
||||||
function useFoo(propVal: {+baz: number}) {
|
function useFoo(propVal: {+baz: number}) {
|
||||||
return <div>{(propVal.baz as number)}</div>;
|
return <div>{(propVal.baz as number)}</div>;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
noFormat: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'compilationMode-infer',
|
||||||
|
input: `// @compilationMode(infer)
|
||||||
|
function nonReactFn() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
noFormat: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'compilationMode-all',
|
||||||
|
input: `// @compilationMode(all)
|
||||||
|
function nonReactFn() {
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
noFormat: true,
|
noFormat: true,
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import BabelPluginReactCompiler, {
|
|||||||
CompilerPipelineValue,
|
CompilerPipelineValue,
|
||||||
parsePluginOptions,
|
parsePluginOptions,
|
||||||
} from 'babel-plugin-react-compiler/src';
|
} from 'babel-plugin-react-compiler/src';
|
||||||
import {type EnvironmentConfig} from 'babel-plugin-react-compiler/src/HIR/Environment';
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import invariant from 'invariant';
|
import invariant from 'invariant';
|
||||||
import {useSnackbar} from 'notistack';
|
import {useSnackbar} from 'notistack';
|
||||||
@@ -69,23 +68,14 @@ function parseInput(
|
|||||||
function invokeCompiler(
|
function invokeCompiler(
|
||||||
source: string,
|
source: string,
|
||||||
language: 'flow' | 'typescript',
|
language: 'flow' | 'typescript',
|
||||||
environment: EnvironmentConfig,
|
options: PluginOptions,
|
||||||
logIR: (pipelineValue: CompilerPipelineValue) => void,
|
|
||||||
): CompilerTransformOutput {
|
): CompilerTransformOutput {
|
||||||
const opts: PluginOptions = parsePluginOptions({
|
|
||||||
logger: {
|
|
||||||
debugLogIRs: logIR,
|
|
||||||
logEvent: () => {},
|
|
||||||
},
|
|
||||||
environment,
|
|
||||||
panicThreshold: 'all_errors',
|
|
||||||
});
|
|
||||||
const ast = parseInput(source, language);
|
const ast = parseInput(source, language);
|
||||||
let result = transformFromAstSync(ast, source, {
|
let result = transformFromAstSync(ast, source, {
|
||||||
filename: '_playgroundFile.js',
|
filename: '_playgroundFile.js',
|
||||||
highlightCode: false,
|
highlightCode: false,
|
||||||
retainLines: true,
|
retainLines: true,
|
||||||
plugins: [[BabelPluginReactCompiler, opts]],
|
plugins: [[BabelPluginReactCompiler, options]],
|
||||||
ast: true,
|
ast: true,
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
configFile: false,
|
configFile: false,
|
||||||
@@ -171,51 +161,59 @@ function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
|
|||||||
try {
|
try {
|
||||||
// Extract the first line to quickly check for custom test directives
|
// Extract the first line to quickly check for custom test directives
|
||||||
const pragma = source.substring(0, source.indexOf('\n'));
|
const pragma = source.substring(0, source.indexOf('\n'));
|
||||||
const config = parseConfigPragmaForTests(pragma);
|
const logIR = (result: CompilerPipelineValue): void => {
|
||||||
|
switch (result.kind) {
|
||||||
transformOutput = invokeCompiler(
|
case 'ast': {
|
||||||
source,
|
break;
|
||||||
language,
|
|
||||||
{...config, customHooks: new Map([...COMMON_HOOKS])},
|
|
||||||
result => {
|
|
||||||
switch (result.kind) {
|
|
||||||
case 'ast': {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'hir': {
|
|
||||||
upsert({
|
|
||||||
kind: 'hir',
|
|
||||||
fnName: result.value.id,
|
|
||||||
name: result.name,
|
|
||||||
value: printFunctionWithOutlined(result.value),
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'reactive': {
|
|
||||||
upsert({
|
|
||||||
kind: 'reactive',
|
|
||||||
fnName: result.value.id,
|
|
||||||
name: result.name,
|
|
||||||
value: printReactiveFunctionWithOutlined(result.value),
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'debug': {
|
|
||||||
upsert({
|
|
||||||
kind: 'debug',
|
|
||||||
fnName: null,
|
|
||||||
name: result.name,
|
|
||||||
value: result.value,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
const _: never = result;
|
|
||||||
throw new Error(`Unhandled result ${result}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
case 'hir': {
|
||||||
|
upsert({
|
||||||
|
kind: 'hir',
|
||||||
|
fnName: result.value.id,
|
||||||
|
name: result.name,
|
||||||
|
value: printFunctionWithOutlined(result.value),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'reactive': {
|
||||||
|
upsert({
|
||||||
|
kind: 'reactive',
|
||||||
|
fnName: result.value.id,
|
||||||
|
name: result.name,
|
||||||
|
value: printReactiveFunctionWithOutlined(result.value),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'debug': {
|
||||||
|
upsert({
|
||||||
|
kind: 'debug',
|
||||||
|
fnName: null,
|
||||||
|
name: result.name,
|
||||||
|
value: result.value,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
const _: never = result;
|
||||||
|
throw new Error(`Unhandled result ${result}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const parsedOptions = parseConfigPragmaForTests(pragma, {
|
||||||
|
compilationMode: 'infer',
|
||||||
|
});
|
||||||
|
const opts: PluginOptions = parsePluginOptions({
|
||||||
|
...parsedOptions,
|
||||||
|
environment: {
|
||||||
|
...parsedOptions.environment,
|
||||||
|
customHooks: new Map([...COMMON_HOOKS]),
|
||||||
},
|
},
|
||||||
);
|
logger: {
|
||||||
|
debugLogIRs: logIR,
|
||||||
|
logEvent: () => {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
transformOutput = invokeCompiler(source, language, opts);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
/**
|
/**
|
||||||
* error might be an invariant violation or other runtime error
|
* error might be an invariant violation or other runtime error
|
||||||
|
|||||||
@@ -9,7 +9,13 @@ import * as t from '@babel/types';
|
|||||||
import {ZodError, z} from 'zod';
|
import {ZodError, z} from 'zod';
|
||||||
import {fromZodError} from 'zod-validation-error';
|
import {fromZodError} from 'zod-validation-error';
|
||||||
import {CompilerError} from '../CompilerError';
|
import {CompilerError} from '../CompilerError';
|
||||||
import {Logger} from '../Entrypoint';
|
import {
|
||||||
|
CompilationMode,
|
||||||
|
Logger,
|
||||||
|
PanicThresholdOptions,
|
||||||
|
parsePluginOptions,
|
||||||
|
PluginOptions,
|
||||||
|
} from '../Entrypoint';
|
||||||
import {Err, Ok, Result} from '../Utils/Result';
|
import {Err, Ok, Result} from '../Utils/Result';
|
||||||
import {
|
import {
|
||||||
DEFAULT_GLOBALS,
|
DEFAULT_GLOBALS,
|
||||||
@@ -683,7 +689,9 @@ const testComplexConfigDefaults: PartialEnvironmentConfig = {
|
|||||||
/**
|
/**
|
||||||
* For snap test fixtures and playground only.
|
* For snap test fixtures and playground only.
|
||||||
*/
|
*/
|
||||||
export function parseConfigPragmaForTests(pragma: string): EnvironmentConfig {
|
function parseConfigPragmaEnvironmentForTest(
|
||||||
|
pragma: string,
|
||||||
|
): EnvironmentConfig {
|
||||||
const maybeConfig: any = {};
|
const maybeConfig: any = {};
|
||||||
// Get the defaults to programmatically check for boolean properties
|
// Get the defaults to programmatically check for boolean properties
|
||||||
const defaultConfig = EnvironmentConfigSchema.parse({});
|
const defaultConfig = EnvironmentConfigSchema.parse({});
|
||||||
@@ -749,6 +757,48 @@ export function parseConfigPragmaForTests(pragma: string): EnvironmentConfig {
|
|||||||
suggestions: null,
|
suggestions: null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
export function parseConfigPragmaForTests(
|
||||||
|
pragma: string,
|
||||||
|
defaults: {
|
||||||
|
compilationMode: CompilationMode;
|
||||||
|
},
|
||||||
|
): PluginOptions {
|
||||||
|
const environment = parseConfigPragmaEnvironmentForTest(pragma);
|
||||||
|
let compilationMode: CompilationMode = defaults.compilationMode;
|
||||||
|
let panicThreshold: PanicThresholdOptions = 'all_errors';
|
||||||
|
for (const token of pragma.split(' ')) {
|
||||||
|
if (!token.startsWith('@')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (token) {
|
||||||
|
case '@compilationMode(annotation)': {
|
||||||
|
compilationMode = 'annotation';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '@compilationMode(infer)': {
|
||||||
|
compilationMode = 'infer';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '@compilationMode(all)': {
|
||||||
|
compilationMode = 'all';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '@compilationMode(syntax)': {
|
||||||
|
compilationMode = 'syntax';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '@panicThreshold(none)': {
|
||||||
|
panicThreshold = 'none';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return parsePluginOptions({
|
||||||
|
environment,
|
||||||
|
compilationMode,
|
||||||
|
panicThreshold,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export type PartialEnvironmentConfig = Partial<EnvironmentConfig>;
|
export type PartialEnvironmentConfig = Partial<EnvironmentConfig>;
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {parseConfigPragmaForTests, validateEnvironmentConfig} from '..';
|
import {parseConfigPragmaForTests, validateEnvironmentConfig} from '..';
|
||||||
|
import {defaultOptions} from '../Entrypoint';
|
||||||
|
|
||||||
describe('parseConfigPragmaForTests()', () => {
|
describe('parseConfigPragmaForTests()', () => {
|
||||||
it('parses flags in various forms', () => {
|
it('parses flags in various forms', () => {
|
||||||
@@ -19,13 +20,18 @@ describe('parseConfigPragmaForTests()', () => {
|
|||||||
|
|
||||||
const config = parseConfigPragmaForTests(
|
const config = parseConfigPragmaForTests(
|
||||||
'@enableUseTypeAnnotations @validateNoSetStateInPassiveEffects:true @validateNoSetStateInRender:false',
|
'@enableUseTypeAnnotations @validateNoSetStateInPassiveEffects:true @validateNoSetStateInRender:false',
|
||||||
|
{compilationMode: defaultOptions.compilationMode},
|
||||||
);
|
);
|
||||||
expect(config).toEqual({
|
expect(config).toEqual({
|
||||||
...defaultConfig,
|
...defaultOptions,
|
||||||
enableUseTypeAnnotations: true,
|
panicThreshold: 'all_errors',
|
||||||
validateNoSetStateInPassiveEffects: true,
|
environment: {
|
||||||
validateNoSetStateInRender: false,
|
...defaultOptions.environment,
|
||||||
enableResetCacheOnSourceFileChanges: false,
|
enableUseTypeAnnotations: true,
|
||||||
|
validateNoSetStateInPassiveEffects: true,
|
||||||
|
validateNoSetStateInRender: false,
|
||||||
|
enableResetCacheOnSourceFileChanges: false,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,12 +11,9 @@ import {transformFromAstSync} from '@babel/core';
|
|||||||
import * as BabelParser from '@babel/parser';
|
import * as BabelParser from '@babel/parser';
|
||||||
import {NodePath} from '@babel/traverse';
|
import {NodePath} from '@babel/traverse';
|
||||||
import * as t from '@babel/types';
|
import * as t from '@babel/types';
|
||||||
import assert from 'assert';
|
|
||||||
import type {
|
import type {
|
||||||
CompilationMode,
|
|
||||||
Logger,
|
Logger,
|
||||||
LoggerEvent,
|
LoggerEvent,
|
||||||
PanicThresholdOptions,
|
|
||||||
PluginOptions,
|
PluginOptions,
|
||||||
CompilerReactTarget,
|
CompilerReactTarget,
|
||||||
CompilerPipelineValue,
|
CompilerPipelineValue,
|
||||||
@@ -51,31 +48,13 @@ function makePluginOptions(
|
|||||||
ValueKindEnum: typeof ValueKind,
|
ValueKindEnum: typeof ValueKind,
|
||||||
): [PluginOptions, Array<{filename: string | null; event: LoggerEvent}>] {
|
): [PluginOptions, Array<{filename: string | null; event: LoggerEvent}>] {
|
||||||
let gating = null;
|
let gating = null;
|
||||||
let compilationMode: CompilationMode = 'all';
|
|
||||||
let panicThreshold: PanicThresholdOptions = 'all_errors';
|
|
||||||
let hookPattern: string | null = null;
|
let hookPattern: string | null = null;
|
||||||
// TODO(@mofeiZ) rewrite snap fixtures to @validatePreserveExistingMemo:false
|
// TODO(@mofeiZ) rewrite snap fixtures to @validatePreserveExistingMemo:false
|
||||||
let validatePreserveExistingMemoizationGuarantees = false;
|
let validatePreserveExistingMemoizationGuarantees = false;
|
||||||
let customMacros: null | Array<Macro> = null;
|
let customMacros: null | Array<Macro> = null;
|
||||||
let validateBlocklistedImports = null;
|
let validateBlocklistedImports = null;
|
||||||
let enableFire = false;
|
|
||||||
let target: CompilerReactTarget = '19';
|
let target: CompilerReactTarget = '19';
|
||||||
|
|
||||||
if (firstLine.indexOf('@compilationMode(annotation)') !== -1) {
|
|
||||||
assert(
|
|
||||||
compilationMode === 'all',
|
|
||||||
'Cannot set @compilationMode(..) more than once',
|
|
||||||
);
|
|
||||||
compilationMode = 'annotation';
|
|
||||||
}
|
|
||||||
if (firstLine.indexOf('@compilationMode(infer)') !== -1) {
|
|
||||||
assert(
|
|
||||||
compilationMode === 'all',
|
|
||||||
'Cannot set @compilationMode(..) more than once',
|
|
||||||
);
|
|
||||||
compilationMode = 'infer';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (firstLine.includes('@gating')) {
|
if (firstLine.includes('@gating')) {
|
||||||
gating = {
|
gating = {
|
||||||
source: 'ReactForgetFeatureFlag',
|
source: 'ReactForgetFeatureFlag',
|
||||||
@@ -96,10 +75,6 @@ function makePluginOptions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstLine.includes('@panicThreshold(none)')) {
|
|
||||||
panicThreshold = 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
let eslintSuppressionRules: Array<string> | null = null;
|
let eslintSuppressionRules: Array<string> | null = null;
|
||||||
const eslintSuppressionMatch = /@eslintSuppressionRules\(([^)]+)\)/.exec(
|
const eslintSuppressionMatch = /@eslintSuppressionRules\(([^)]+)\)/.exec(
|
||||||
firstLine,
|
firstLine,
|
||||||
@@ -130,10 +105,6 @@ function makePluginOptions(
|
|||||||
validatePreserveExistingMemoizationGuarantees = true;
|
validatePreserveExistingMemoizationGuarantees = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstLine.includes('@enableFire')) {
|
|
||||||
enableFire = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const hookPatternMatch = /@hookPattern:"([^"]+)"/.exec(firstLine);
|
const hookPatternMatch = /@hookPattern:"([^"]+)"/.exec(firstLine);
|
||||||
if (
|
if (
|
||||||
hookPatternMatch &&
|
hookPatternMatch &&
|
||||||
@@ -199,10 +170,11 @@ function makePluginOptions(
|
|||||||
debugLogIRs: debugIRLogger,
|
debugLogIRs: debugIRLogger,
|
||||||
};
|
};
|
||||||
|
|
||||||
const config = parseConfigPragmaFn(firstLine);
|
const config = parseConfigPragmaFn(firstLine, {compilationMode: 'all'});
|
||||||
const options = {
|
const options = {
|
||||||
|
...config,
|
||||||
environment: {
|
environment: {
|
||||||
...config,
|
...config.environment,
|
||||||
moduleTypeProvider: makeSharedRuntimeTypeProvider({
|
moduleTypeProvider: makeSharedRuntimeTypeProvider({
|
||||||
EffectEnum,
|
EffectEnum,
|
||||||
ValueKindEnum,
|
ValueKindEnum,
|
||||||
@@ -212,12 +184,9 @@ function makePluginOptions(
|
|||||||
hookPattern,
|
hookPattern,
|
||||||
validatePreserveExistingMemoizationGuarantees,
|
validatePreserveExistingMemoizationGuarantees,
|
||||||
validateBlocklistedImports,
|
validateBlocklistedImports,
|
||||||
enableFire,
|
|
||||||
},
|
},
|
||||||
compilationMode,
|
|
||||||
logger,
|
logger,
|
||||||
gating,
|
gating,
|
||||||
panicThreshold,
|
|
||||||
noEmit: false,
|
noEmit: false,
|
||||||
eslintSuppressionRules,
|
eslintSuppressionRules,
|
||||||
flowSuppressions,
|
flowSuppressions,
|
||||||
|
|||||||
Reference in New Issue
Block a user