Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @compilationMode(infer)
function nonReactFn() {
  return {};
}
18 changes: 18 additions & 0 deletions compiler/apps/playground/__tests__/e2e/page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,24 @@ function Foo() {
// @flow
function useFoo(propVal: {+baz: number}) {
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,
Expand Down
107 changes: 53 additions & 54 deletions compiler/apps/playground/components/Editor/EditorImpl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import BabelPluginReactCompiler, {
CompilerPipelineValue,
parsePluginOptions,
} from 'babel-plugin-react-compiler/src';
import {type EnvironmentConfig} from 'babel-plugin-react-compiler/src/HIR/Environment';
import clsx from 'clsx';
import invariant from 'invariant';
import {useSnackbar} from 'notistack';
Expand Down Expand Up @@ -69,22 +68,14 @@ function parseInput(
function invokeCompiler(
source: string,
language: 'flow' | 'typescript',
environment: EnvironmentConfig,
logIR: (pipelineValue: CompilerPipelineValue) => void,
options: PluginOptions,
): CompilerTransformOutput {
const opts: PluginOptions = parsePluginOptions({
logger: {
debugLogIRs: logIR,
logEvent: () => {},
},
environment,
});
const ast = parseInput(source, language);
let result = transformFromAstSync(ast, source, {
filename: '_playgroundFile.js',
highlightCode: false,
retainLines: true,
plugins: [[BabelPluginReactCompiler, opts]],
plugins: [[BabelPluginReactCompiler, options]],
ast: true,
sourceType: 'module',
configFile: false,
Expand Down Expand Up @@ -170,51 +161,59 @@ function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
try {
// Extract the first line to quickly check for custom test directives
const pragma = source.substring(0, source.indexOf('\n'));
const config = parseConfigPragmaForTests(pragma);

transformOutput = invokeCompiler(
source,
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}`);
}
const logIR = (result: CompilerPipelineValue): void => {
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}`);
}
}
};
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) {
/**
* error might be an invariant violation or other runtime error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ import * as t from '@babel/types';
import {ZodError, z} from 'zod';
import {fromZodError} from 'zod-validation-error';
import {CompilerError} from '../CompilerError';
import {Logger} from '../Entrypoint';
import {
CompilationMode,
Logger,
PanicThresholdOptions,
parsePluginOptions,
PluginOptions,
} from '../Entrypoint';
import {Err, Ok, Result} from '../Utils/Result';
import {
DEFAULT_GLOBALS,
Expand Down Expand Up @@ -683,7 +689,9 @@ const testComplexConfigDefaults: PartialEnvironmentConfig = {
/**
* For snap test fixtures and playground only.
*/
export function parseConfigPragmaForTests(pragma: string): EnvironmentConfig {
function parseConfigPragmaEnvironmentForTest(
pragma: string,
): EnvironmentConfig {
const maybeConfig: any = {};
// Get the defaults to programmatically check for boolean properties
const defaultConfig = EnvironmentConfigSchema.parse({});
Expand Down Expand Up @@ -749,6 +757,48 @@ export function parseConfigPragmaForTests(pragma: string): EnvironmentConfig {
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>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import {parseConfigPragmaForTests, validateEnvironmentConfig} from '..';
import {defaultOptions} from '../Entrypoint';

describe('parseConfigPragmaForTests()', () => {
it('parses flags in various forms', () => {
Expand All @@ -19,13 +20,18 @@ describe('parseConfigPragmaForTests()', () => {

const config = parseConfigPragmaForTests(
'@enableUseTypeAnnotations @validateNoSetStateInPassiveEffects:true @validateNoSetStateInRender:false',
{compilationMode: defaultOptions.compilationMode},
);
expect(config).toEqual({
...defaultConfig,
enableUseTypeAnnotations: true,
validateNoSetStateInPassiveEffects: true,
validateNoSetStateInRender: false,
enableResetCacheOnSourceFileChanges: false,
...defaultOptions,
panicThreshold: 'all_errors',
environment: {
...defaultOptions.environment,
enableUseTypeAnnotations: true,
validateNoSetStateInPassiveEffects: true,
validateNoSetStateInRender: false,
enableResetCacheOnSourceFileChanges: false,
},
});
});
});
37 changes: 3 additions & 34 deletions compiler/packages/snap/src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,9 @@ import {transformFromAstSync} from '@babel/core';
import * as BabelParser from '@babel/parser';
import {NodePath} from '@babel/traverse';
import * as t from '@babel/types';
import assert from 'assert';
import type {
CompilationMode,
Logger,
LoggerEvent,
PanicThresholdOptions,
PluginOptions,
CompilerReactTarget,
CompilerPipelineValue,
Expand Down Expand Up @@ -51,31 +48,13 @@ function makePluginOptions(
ValueKindEnum: typeof ValueKind,
): [PluginOptions, Array<{filename: string | null; event: LoggerEvent}>] {
let gating = null;
let compilationMode: CompilationMode = 'all';
let panicThreshold: PanicThresholdOptions = 'all_errors';
let hookPattern: string | null = null;
// TODO(@mofeiZ) rewrite snap fixtures to @validatePreserveExistingMemo:false
let validatePreserveExistingMemoizationGuarantees = false;
let customMacros: null | Array<Macro> = null;
let validateBlocklistedImports = null;
let enableFire = false;
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')) {
gating = {
source: 'ReactForgetFeatureFlag',
Expand All @@ -96,10 +75,6 @@ function makePluginOptions(
}
}

if (firstLine.includes('@panicThreshold(none)')) {
panicThreshold = 'none';
}

let eslintSuppressionRules: Array<string> | null = null;
const eslintSuppressionMatch = /@eslintSuppressionRules\(([^)]+)\)/.exec(
firstLine,
Expand Down Expand Up @@ -130,10 +105,6 @@ function makePluginOptions(
validatePreserveExistingMemoizationGuarantees = true;
}

if (firstLine.includes('@enableFire')) {
enableFire = true;
}

const hookPatternMatch = /@hookPattern:"([^"]+)"/.exec(firstLine);
if (
hookPatternMatch &&
Expand Down Expand Up @@ -199,10 +170,11 @@ function makePluginOptions(
debugLogIRs: debugIRLogger,
};

const config = parseConfigPragmaFn(firstLine);
const config = parseConfigPragmaFn(firstLine, {compilationMode: 'all'});
const options = {
...config,
environment: {
...config,
...config.environment,
moduleTypeProvider: makeSharedRuntimeTypeProvider({
EffectEnum,
ValueKindEnum,
Expand All @@ -212,12 +184,9 @@ function makePluginOptions(
hookPattern,
validatePreserveExistingMemoizationGuarantees,
validateBlocklistedImports,
enableFire,
},
compilationMode,
logger,
gating,
panicThreshold,
noEmit: false,
eslintSuppressionRules,
flowSuppressions,
Expand Down
10 changes: 10 additions & 0 deletions fixtures/view-transition/src/components/Chrome.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ export default class Chrome extends Component {
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="shortcut icon" href="favicon.ico" />
<link rel="stylesheet" href={assets['main.css']} />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link
rel="preconnect"
href="https://fonts.gstatic.com"
crossOrigin=""
/>
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap"
rel="stylesheet"
/>
<title>{this.props.title}</title>
</head>
<body>
Expand Down
Loading
Loading