ksFollowRulesOfReact
function Component(props) {
  const logEvent = useLogging(props.appId);
  const [currentStep, setCurrentStep] = useState(0);

  // onSubmit gets the same mutable range as `logEvent`, since that is called
  // later. however, our validation uses direct aliasing to track function
  // expressions which are invoked, and understands that this function isn't
  // called during render:
  const onSubmit = errorEvent => {
    logEvent(errorEvent);
    setCurrentStep(1);
  };

  switch (currentS

={{foo: 'bar'}} />;
    case 1:
      return <OtherComponent data={{foo: 'joe'}} onSubmit={onSubmit} />;
    default:
      // 1. logEvent's mutable range is extended to this instruction
      logEvent('Invalid step');
      return <OtherComponent data={nu

tep) {
    case 0:
      return <OtherComponent data


from 'react';

function Component(props) {
  const items = props.items ? props.items.slice() : [];
  const [state] = useState('');
  return props.cond ? (

{state}

  ) : (

      {items.map(item => (

{item.name}

      ))}

  );
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{cond: false, items: [{id: 0, name: 'Alice'}]}],
  sequentialRenders: [
    {cond: false, items: [{id: 0, name: 'Alice'}]},
    {
      cond: false,

  {id: 1, name: 'Bob'},
      ],
    },
    {
      cond: true,
      items: [
        {id: 0, name: 'Alice'},
        {id: 1, name: 'Bob'},
      ],
    },
    {
      cond: false,
      items: [
        {id: 1, name: 'Bob'},
        {id: 2, name: 'Claire

     items: [
        {id: 0, name: 'Alice'},


import {makeArray, Stringify, useIdentity} from 'shared-runtime';

/**
 * Example showing that returned inner function expressions should not be
 * typed with `freeze` effects.
 * Also see repro-returned-inner-fn-mutates-context
 */
function Foo({b}) {
  'use memo';

  const fnFactory = () => {
    /**
     * This returned function expression *is* a local value. But it might (1)
     * capture and mutate its context environment and (2) be called during
     * render.
     * Typing it with `freeze` effects w

ole.log('b');
  useIdentity();

  const fn = fnFactory();
  const arr = makeArray(b);
  fn(arr);
  return <Stringify cb={myVar} value={arr} shouldInvokeFns={true} />;
}

export const FIXTURE_ENTRYPOINT = {
  fn: Foo,
  params: [{b: 1}],
  sequentialRenders

ould be incorrect as it would mean
     * inferring that calls to updaterFactory()() do not mutate its captured
     * context.
     */
    return () => {
      myVar = () => console.log('a');
    };
  };
  let myVar = () => cons


ableNewMutationAliasingModel
import {ValidateMemoization} from 'shared-runtime';

const Codes = {
  en: {name: 'English'},
  ja: {name: 'Japanese'},
  ko: {name: 'Korean'},
  zh: {name: 'Chinese'},
};

function Component(a) {
  let keys;
  if (a) {
    keys = Object.keys(Codes);
  } else {
    return null;
  }
  const options = keys.map(code => {
    // In the old inference model, `keys` was assumed to be mutated bc
    // this callback captures its input into its output, and the return
    // is treated as

   <>
      <ValidateMemoization inputs={[]} output={keys} onlyCheckCompiled={true} />
      <ValidateMemoization
        inputs={[]}
        output={options}
        onlyCheckCompiled={true}
      />
    </>
  );
}

export const FIXTURE_ENTRYPOINT = {
  f

 a mutation since it's a function expression. The new
    // model understands that `code` is captured but not mutated.
    const country = Codes[code];
    return {
      name: country.name,
      code,
    };
  });
  return (


lidateMemoization} from 'shared-runtime';

/**
 * Fixture for granular iterator semantics:
 * 1. ConditionallyMutate the iterator itself, depending on whether the iterator
 *    is a mutable iterator.
 * 2. Capture effect on elements within the iterator.
 */
function Validate({x, input}) {
  'use no memo';
  return (
    <>
      <ValidateMemoization inputs={[]} output={x[0]} onlyCheckCompiled={true} />
      <ValidateMemoization
        inputs={[input]}
        output={x[1]}
        onlyCheckCompiled={true

 'use memo';
  /**
   * We should be able to memoize {} separately from `x`.
   */
  const x = Array.from([{}]);
  useIdentity();
  x.push([input]);
  return <Validate x={x} input={input} />;
}

export const FIXTURE_ENTRYPOINT = {
  fn: useFoo,
  params: [

}
      />
    </>
  );
}
function useFoo(input) {


ponent({a, b, cond, items}) {
  try {
    const x = a?.value;
    // items.length is accessed WITHIN the ternary expression - throws if items is null
    const y = cond ? b?.first : items.length;
    const z = x && y;
    return (

        {String(x)}-{String(y)}-{String(z)}

    );
  } catch {
    return
error
;
  }
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [
    {
      a: {value: 'A'},
      b: {first: 'B1', second: 'B2'},
      cond: true,
      i

B2'},
      cond: true,
      items: [1, 2, 3],
    },
    {
      a: {value: 'A'},
      b: {first: 'B1', second: 'B2'},
      cond: false,
      items: [1, 2],
    },
    {a: null, b: {first: 'B1', second: 'B2'}, cond: true, items: [1, 2, 3]},
    {a: {v

tems: [1, 2, 3],
    },
  ],
  sequentialRenders: [
    {
      a: {value: 'A'},
      b: {first: 'B1', second: 'B2'},
      cond: true,
      items: [1, 2, 3],
    },
    {
      a: {value: 'A'},
      b: {first: 'B1', second: '


useMemo} from 'react';
import {typedArrayPush, ValidateMemoization} from 'shared-runtime';

export function Component({a, b}) {
  const item1 = useMemo(() => ({a}), [a]);
  const item2 = useMemo(() => ({b}), [b]);
  const items = useMemo(() => {
    const items = [];
    typedArrayPush(items, item1);
    typedArrayPush(items, item2);
    return items;
  }, [item1, item2]);

  return (
    <>
      <ValidateMemoization inputs={[a]} output={items[0]} />
      <ValidateMemoization inputs={[b]} output={items[1]

ut={items} />
    </>
  );
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{a: 0, b: 0}],
  sequentialRenders: [
    {a: 0, b: 0},
    {a: 1, b: 0},
    {a: 1, b: 1},
    {a: 1, b: 2},
    {a: 2, b: 2},
    {a: 3, b: 2},
    {a: 0, b: 0}

} />
      <ValidateMemoization inputs={[a, b]} outp


y, makeObject_Primitives, mutate, useHook} from 'shared-runtime';

function Component(props) {
  // With the feature enabled these variables are inferred as frozen as of
  // the useMemo call
  const free = makeObject_Primitives();
  const free2 = makeObject_Primitives();
  const part = free2.part;

  // Thus their mutable range ends prior to this hook call, and both the above
  // values and the useMemo block value can be memoized
  useHook();

  const object = useMemo(() => {
    const x = makeObject_Prim

ree, part);
    return x;
  }, [props.value, free, part]);

  // These calls should be inferred as non-mutating due to the above freeze inference
  identity(free);
  identity(part);

  return object;
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,

itives();
    x.value = props.value;
    mutate(x, f


tringify} from 'shared-runtime';

/**
 * Repro from https://github.com/facebook/react/issues/34262
 *
 * The compiler memoizes more precisely than the original code, with two reactive scopes:
 * - One for `transform(input)` with `input` as dep
 * - One for `{value}` with `value` as dep
 *
 * Previously ValidatePreservedManualMemoization rejected this input, because
 * the original memoization had `object` depending on `input` but we split the scope per above,
 * and the scope for the FinishMemoize instructi

function useInputValue(input) {
  const object = React.useMemo(() => {
    const {value} = identity(input);
    return {value};
  }, [input]);
  return object;
}

function Component() {
  return <Stringify value={useInputValue({value: 42}).value} />;
}

ex

on is the second scope which depends on `value`
 */


r the ideal scopes, not what is currently
// emitted
function foo(props) {
  // scope 0: deps=[props.a] decl=[x] reassign=none
  let x = [];
  x.push(props.a);

  // scope 1: deps=[x] decl=[header] reassign=none
  const header = props.showHeader ? <div>{x}</div> : null;

  // scope 2:
  // deps=[x, props.b, props.c]
  // decl=none
  // reassign=[x]
  const y = [x]; // y depends on the earlier x
  x = []; // x reassigned
  y.push(props.b); // interleaved mutation of x/y
  x.push(props.c); // interleaved muta

pe 3 ...
  const content = (
    <div>
      {x}
      {y}
    </div>
  );

  // scope 4 ...
  return (
    <>
      {header}
      {content}
    </>
  );
}

export const FIXTURE_ENTRYPOINT = {
  fn: foo,
  params: ['TodoAdd'],
  isComponent: 'TodoAdd',
};


function Component({data, fallback}) {
  try {
    // fallback.default is accessed WITHIN the optional chain via nullish coalescing
    const value = data?.nested?.deeply?.value ?? fallback.default;
    return
{value}
;
  } catch {
    return
error
;
  }
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [
    {data: {nested: {deeply: {value: 'found'}}}, fallback: {default: 'none'}},
  ],
  sequentialRenders: [
    {data: {nested: {deeply: {value: 'found'}}}, fallback: {de

ult: 'none'}}, // uses fallback.default
    {data: {nested: null}, fallback: {default: 'none'}}, // uses fallback.default
    {data: null, fallback: null}, // errors because fallback.default throws
    {data: {nested: {deeply: {value: 42}}}, fallback: {def

fault: 'none'}},
    {data: {nested: {deeply: {value: 'found'}}}, fallback: {default: 'none'}},
    {data: {nested: {deeply: {value: 'changed'}}}, fallback: {default: 'none'}},
    {data: {nested: {deeply: null}}, fallback: {defa


import {useEffect, useState} from 'react';

/**
 * Example of a function expression whose return value shouldn't have
 * a "freeze" effect on all operands.
 *
 * This is because the function expression is passed to `useEffect` and
 * thus is not a render function. `cleanedUp` is also created within
 * the effect and is not a render variable.
 */
function Component({prop}) {
  const [cleanupCount, setCleanupCount] = useState(0);

  useEffect(() => {
    let cleanedUp = false;
    setTimeout(() => {
      if

eanedUp = true;
        setCleanupCount(c => c + 1);
      }
    };
  }, [prop]);
  return <div>{cleanupCount}</div>;
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{prop: 5}],
  sequentialRenders: [{prop: 5}, {prop: 5}, {prop: 6}],
};

(!cleanedUp) {
        cleanedUp = true;
        setCleanupCount(c => c + 1);
      }
    }, 0);
    // This return value should not have freeze effects
    // on its operands
    return () => {
      if (!cleanedUp) {
        cl


@enableNewMutationAliasingModel
import {identity, mutate} from 'shared-runtime';

/**
 * Fixed in the new inference model.
 *
 * Bug: copy of error.todo-object-expression-computed-key-modified-during-after-construction-sequence-expr
 * with the mutation hoisted to a named variable instead of being directly
 * inlined into the Object key.
 *
 * Found differences in evaluator results
 *   Non-forget (expected):
 *   (kind: ok) [{"[object Object]":[42]},{"wat0":"joe","wat1":"joe"}]
 *   [{"[object Object]":[42

key = {};
  const tmp = (mutate(key), key);
  const context = {
    // Here, `tmp` is frozen (as it's inferred to be a primitive/string)
    [tmp]: identity([props.value]),
  };
  mutate(key);
  return [context, key];
}

export const FIXTURE_ENTRYPOINT = {

]},{"wat0":"joe","wat1":"joe"}]
 *   Forget:
 *   (kind: ok) [{"[object Object]":[42]},{"wat0":"joe","wat1":"joe"}]
 *   [{"[object Object]":[42]},{"wat0":"joe","wat1":"joe","wat2":"joe"}]
 */
function Component(props) {
  const


ps) {
  const x = {};
  let y;
  if (props.cond) {
    if (props.cond2) {
      y = [props.value];
    } else {
      y = [props.value2];
    }
  } else {
    y = [];
  }
  // This should be inferred as `<store> y` s.t. `x` can still
  // be independently memoized. *But* this also must properly
  // extend the mutable range of the array literals in the
  // if/else branches
  y.push(x);

  return [x, y];
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{cond: true, cond2: true, value: 42}]

e, value: 3.14},
    {cond: true, cond2: true, value: 42},
    {cond: true, cond2: true, value: 3.14},
    {cond: true, cond2: false, value2: 3.14},
    {cond: true, cond2: false, value2: 42},
    {cond: true, cond2: false, value2: 3.14},
    {cond: false}

,
  sequentialRenders: [
    {cond: true, cond2: tru


**
 * 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 {memo} from 'react';

export const IconGitHub = memo<JSX.IntrinsicElements['svg']>(
  function IconGitHub(props) {
    return (
      <svg
        xmlns="http://www.w3.org/2000/svg"
        width="1.5em"
        height="1.5em"
        viewBox="0 -2 24 24"
        fill="currentColor"
        {...props}>
        <p


ight (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 '../styles/globals.css';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}): JSX.Element {
  'use no memo';
  return (
    <html lang="en">
      <head>
        <title>
          {process.env.NODE_ENV === 'development'
            ? '[DEV] React Compiler Playground'
            : 'React C

   <link rel="manifest" href="/site.webmanifest" />
        <link
          rel="preload"
          href="/fonts/Source-Code-Pro-Regular.woff2"
          as="font"
          type="font/woff2"
          crossOrigin="anonymous"
        />
        <link

ompiler Playground'}
        </title>
        <meta
          name="viewport"
          content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"></meta>
        <link rel="icon" href="/favicon.ico" />


'shared-runtime';

/**
 * Fixture to assert that we can infer the type and effects of an array created
 * with `Array.from`.
 */
function Validate({x, val1, val2}) {
  'use no memo';
  return (
    <>
      <ValidateMemoization
        inputs={[val1]}
        output={x[0]}
        onlyCheckCompiled={true}
      />
      <ValidateMemoization
        inputs={[val2]}
        output={x[1]}
        onlyCheckCompiled={true}
      />
    </>
  );
}
function useFoo({val1, val2}) {
  'use memo';
  const x = Array.fr

[val2]);
  return <Validate x={x} val1={val1} val2={val2} />;
}

export const FIXTURE_ENTRYPOINT = {
  fn: useFoo,
  params: [{val1: 1, val2: 2}],
  params: [
    {val1: 1, val2: 2},
    {val1: 1, val2: 2},
    {val1: 1, val2: 3},
    {val1: 4, val2: 2},

om([]);
  useIdentity();
  x.push([val1]);
  x.push(


llowRulesOfReact @enableTransitivelyFreezeFunctionExpressions @validateExhaustiveMemoizationDependencies:false
import {useCallback} from 'react';

function Component({entity, children}) {
  const showMessage = useCallback(() => entity != null);

  // We currently model functions as if they could escape intor their return value
  // but if we ever changed that (or did optimization to figure out cases where they
  // are known not to) we could get a false positive validation error here, since
  // showMessage

in this instance.
  const shouldShowMessage = showMessage();
  return (

{shouldShowMessage}

{children}

  );
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [
    {
      entity: {nam

doesn't need to be memoized since it doesn't escape


ight (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 * as React from 'react';
import {render} from '@testing-library/react';
import {expectLogsAndClear, log} from './expectLogs';

function Hello({name}) {
  const items = [1, 2, 3].map(item => {
    log(`recomputing ${item}`);
    return
Item {item}
;
  });
  return (

      Hello{name}

World

          Item 1

          Item 2

          Item 3

    </DocumentFragment>
  `);

  expectLogsAndClear(['recomputing 1', 'recomput

   {items}
    </div>
  );
}

test('hello', () => {
  const {asFragment, rerender} = render(<Hello name="World" />);

  expect(asFragment()).toMatchInlineSnapshot(`
    <DocumentFragment>
      <div>
        Hello
        <b>


ight (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 {render, screen, fireEvent} from '@testing-library/react';
import * as React from 'react';
import {expectLogsAndClear, log} from './expectLogs';

function Counter(props) {
  'use memo';
  let value = props.value;
  let a = value++;
  expect(a).toBe(props.value); // postfix
  let b = ++value;
  expect(b).toBe(props.value + 2

ue;
  expect(f).toBe(props.value);
  expect(value).toBe(props.value);
  return <span>{value}</span>;
}

test('use-state', async () => {
  const {asFragment, rerender} = render(<Counter value={0} />);
  expect(asFragment()).toMatchInlineSnapshot(`
    <Docu

); // previous postfix operation + prefix operation
  let c = ++value;
  expect(c).toBe(props.value + 3);
  let d = value--;
  expect(d).toBe(props.value + 3);
  let e = --value;
  expect(e).toBe(props.value + 1);
  let f = --val


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

/**
 * Sync from <https://github.com/reactjs/reactjs.org/blob/main/beta/colors.js>.
 */

module.exports = {
  // Text colors
  primary: '#23272F', // gray-90
  'primary-dark': '#F6F7F9', // gray-5
  secondary: '#404756', // gray-70
  'secondary-dark': '#EBECF0', // gray-10
  link: '#087EA4', // blue-50
  'link-dark': '#149ECA', // blue-40
  syntax: '#EBECF0', // gray-1


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import {defineConfig, devices} from '@playwright/test';
import path from 'path';

// Use process.env.PORT by default and fallback to port 3000
const PORT = process.env.PORT || 3000;

// Set webServer.url and use.baseURL with the location of the WebServer respecting the correct set port
const baseURL = `http://localhost:${PORT}`;

// Reference: https://playwright.dev/do

a test fails, retry it additional 2 times
  retries: 3,
  // Artifacts folder where screenshots, videos, and traces are stored.
  outputDir: 'test-results/',
  // Note: we only use text snapshots, so its safe to omit the host environment name
  snapshotPat

cs/test-configuration
export default defineConfig({
  // Timeout per test
  timeout: 30 * 1000,
  // Run all tests in parallel.
  fullyParallel: true,
  // Test directory
  testDir: path.join(__dirname, '__tests__/e2e'),
  // If


/**
 * 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.
 */

const {execSync} = require('child_process');

// So that we don't need to check them into the repo.
// See https://github.com/reactjs/reactjs.org/blob/main/beta/scripts/downloadFonts.js.
execSync(
  'curl https://conf.reactjs.org/fonts/Optimistic_Display_W_Lt.woff2 --output public/fonts/Optimistic_Display_W_Lt.woff2'
)

'curl https://conf.reactjs.org/fonts/Optimistic_Display_W_Md.woff2 --output public/fonts/Optimistic_Display_W_Md.woff2'
);
execSync(
  'curl https://conf.reactjs.org/fonts/Optimistic_Display_W_Bd.woff2 --output public/fonts/Optimistic_Display_W_Bd.woff2'
)


 MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import {RefreshIcon, ShareIcon} from '@heroicons/react/outline';
import {CheckIcon} from '@heroicons/react/solid';
import clsx from 'clsx';
import Link from 'next/link';
import {useSnackbar} from 'notistack';
import {
  useState,
  startTransition,
  unstable_addTransitionType as addTransitionType,
} from 'react';
import {defaultStore} from '../lib/defaultStore';
import {IconGitHub} from './Icons/IconGitHub';
import Lo

 useState(false);
  const store = useStore();
  const dispatchStore = useStoreDispatch();
  const {enqueueSnackbar, closeSnackbar} = useSnackbar();

  const handleReset: () => void = () => {
    if (confirm('Are you sure you want to reset the playground?')

go from './Logo';
import {useStore, useStoreDispatch} from './StoreContext';
import {TOGGLE_INTERNALS_TRANSITION} from '../lib/transitionTypes';

export default function Header(): JSX.Element {
  const [showCheck, setShowCheck] =


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import {
  BanIcon,
  ExclamationIcon,
  InformationCircleIcon,
  XIcon,
} from '@heroicons/react/solid';
import {CustomContentProps, SnackbarContent, useSnackbar} from 'notistack';
import {forwardRef} from 'react';
import {MessageLevel, MessageSource} from '../lib/stores';

// https://notistack.com/examples/advanced/custom-component#custom-variant-(typescript)
declare

tring;
  level: MessageLevel;
  source: MessageSource;
  codeframe: string | undefined;
}

const Message = forwardRef<HTMLDivElement, MessageProps>(
  ({id, title, level, source, codeframe}, ref) => {
    const {closeSnackbar} = useSnackbar();
    const is

 module 'notistack' {
  interface VariantOverrides {
    message: {
      title: string;
      level: MessageLevel;
      codeframe: string | undefined;
    };
  }
}

interface MessageProps extends CustomContentProps {
  title: s


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import type {Dispatch, ReactNode} from 'react';
import {useState, useEffect, useReducer} from 'react';
import createContext from '../lib/createContext';
import {emptyStore, defaultStore} from '../lib/defaultStore';
import {
  saveStore,
  initStoreFromUrlOrLocalStorage,
  type Store,
} from '../lib/stores';

const StoreContext = createContext<Store>();

/**
 * Hook to

= StoreDispatchContext.useContext;

/**
 * Make Store and dispatch function available to all sub-components in children.
 */
export function StoreProvider({children}: {children: ReactNode}): JSX.Element {
  const [store, dispatch] = useReducer(storeReducer

access the store.
 */
export const useStore = StoreContext.useContext;

const StoreDispatchContext = createContext<Dispatch<ReducerAction>>();

/**
 * Hook to access the store dispatch function.
 */
export const useStoreDispatch


oEditor, {loader, type Monaco} from '@monaco-editor/react';
import {
  CompilerErrorDetail,
  CompilerDiagnostic,
} from 'babel-plugin-react-compiler';
import invariant from 'invariant';
import type {editor} from 'monaco-editor';
import * as monaco from 'monaco-editor';
import {
  useEffect,
  useState,
  unstable_ViewTransition as ViewTransition,
} from 'react';
import {renderReactCompilerMarkers} from '../../lib/reactCompilerMonacoDiagnostics';
import {useStore, useStoreDispatch} from '../StoreContext';
i

 loading them with webpack.
import React$Types from '../../node_modules/@types/react/index.d.ts';

loader.config({monaco});

type Props = {
  errors: Array<CompilerErrorDetail | CompilerDiagnostic>;
  language: 'flow' | 'typescript';
};

export default fun

mport TabbedWindow from '../TabbedWindow';
import {monacoOptions} from './monacoOptions';
import {CONFIG_PANEL_TRANSITION} from '../../lib/transitionTypes';

// @ts-expect-error TODO: Make TS recognize .d.ts files, in addition to


  type CompilerError,
} from 'babel-plugin-react-compiler';
import parserBabel from 'prettier/plugins/babel';
import * as prettierPluginEstree from 'prettier/plugins/estree';
import * as prettier from 'prettier/standalone';
import {type Store} from '../../lib/stores';
import {
  memo,
  ReactNode,
  use,
  useState,
  Suspense,
  unstable_ViewTransition as ViewTransition,
  unstable_addTransitionType as addTransitionType,
  startTransition,
} from 'react';
import AccordionWindow from '../AccordionWindow';
i

ON,
} from '../../lib/transitionTypes';
import {LRUCache} from 'lru-cache';

const MemoizedOutput = memo(Output);

export default MemoizedOutput;

export const BASIC_OUTPUT_TAB_NAMES = ['Output', 'SourceMap'];

const tabifyCache = new LRUCache<Store, Promi

mport TabbedWindow from '../TabbedWindow';
import {monacoOptions} from './monacoOptions';
import {BabelFileResult} from '@babel/core';
import {
  CONFIG_PANEL_TRANSITION,
  TOGGLE_INTERNALS_TRANSITION,
  EXPAND_ACCORDION_TRANSITI


ectness property.
// When propagating reactive dependencies of an inner scope up to its parent,
// we prefer to retain granularity.
//
// In this test, we check that Forget propagates the inner scope's conditional
// dependencies (e.g. props.a.b) instead of only its derived minimal
// unconditional dependencies (e.g. props).
// ```javascript
//  scope @0 (deps=[???] decls=[x, y]) {
//    let y = {};
//    scope @1 (deps=[props] decls=[x]) {
//      let x = {};
//      if (foo) mutate1(x, props.a.b);
//    }

RUE, setProperty} from 'shared-runtime';

function useJoinCondDepsInUncondScopes(props) {
  let y = {};
  let x = {};
  if (CONST_TRUE) {
    setProperty(x, props.a.b);
  }
  setProperty(y, props.a.b);
  return [x, y];
}

export const FIXTURE_ENTRYPOINT =

//    mutate2(y, props.a.b);
//  }

import {CONST_T


// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:"lint"

function Component() {
  const [foo, setFoo] = useState({});
  const [bar, setBar] = useState(new Set());

  /*
   * isChanged is considered context of the effect's function expression,
   * if we don't bail out of effect mutation derivation tracking, isChanged
   * will inherit the sources of the effect's function expression.
   *
   * This is innacurate and with the multiple passes ends up causing an infinite loop.
   */

> {
    let isChanged = false;

    const newData = foo.map(val => {
      bar.someMethod(val);
      isChanged = true;
    });

    if (isChanged) {
      setFoo(newData);
    }
  }, [foo, bar]);

  return (
    <div>
      {foo}, {bar}
    </div>
  );
}


 from 'react';
import {Stringify} from 'shared-runtime';

/**
 * TODO: we're currently bailing out because `contextVar` is a context variable
 * and not recorded into the PropagateScopeDeps LoadLocal / PropertyLoad
 * sidemap. Previously, we were able to avoid this as `BuildHIR` hoisted
 * `LoadContext` and `PropertyLoad` instructions into the outer function, which
 * we took as eligible dependencies.
 *
 * One solution is to simply record `LoadContext` identifiers into the
 * temporaries sidemap when the i

mutable range.
 */
function Foo(props) {
  let contextVar;
  if (props.cond) {
    contextVar = {val: 2};
  } else {
    contextVar = {};
  }

  const cb = useCallback(() => [contextVar.val], [contextVar.val]);

  return <Stringify cb={cb} shouldInvokeFns=

nstruction occurs *after* the context
 * variable's


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import * as React from 'react';
import {render} from '@testing-library/react';

globalThis.constantValue = 'global test value';

test('literal-constant-propagation', () => {
  function Component() {
    'use memo';
    const x = 'test value 1';
    return <div>{x}</div>;
  }
  const {asFragment, rerender} = render(<Component />);

  expect(asFragment()).toMatchInlineSn

st value 1
      </div>
    </DocumentFragment>
  `);
});

test('global-constant-propagation', () => {
  function Component() {
    'use memo';
    const x = constantValue;

    return <div>{x}</div>;
  }
  const {asFragment, rerender} = render(<Component

apshot(`
    <DocumentFragment>

        test value 1

    </DocumentFragment>
  `);

  rerender(<Component />);

  expect(asFragment()).toMatchInlineSnapshot(`
    <DocumentFragment>

        te


ight (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 {render, screen, fireEvent} from '@testing-library/react';
import * as React from 'react';
import {useState} from 'react';
import {expectLogsAndClear, log} from './expectLogs';

function Counter() {
  let [state, setState] = useState(0);
  return (

      <Title text="Counter" />
      {state}
      <b

{
  const {asFragment} = render(<Counter />);

  expect(asFragment()).toMatchInlineSnapshot(`
  <DocumentFragment>

        Counter

        0

      <button
        data-testid="button"
      >

utton data-testid="button" onClick={() => setState(state + 1)}>
        increment
      </button>
    </div>
  );
}

function Title({text}) {
  log(`rendering: ${text}`);
  return <h1>{text}</h1>;
}

test('use-state', async () =>


/**
 * 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.
 */

const defaultTheme = require('tailwindcss/defaultTheme');
const colors = require('./colors');

module.exports = {
  content: [
    './app/**/*.{js,ts,jsx,tsx}',
    './pages/**/*.{js,ts,jsx,tsx}',
    './components/**/*.{js,ts,jsx,tsx}',
    './lib/forgetMonacoDiagnostics.ts',
  ],
  theme: {
    extend: {
      colors

alc(100vh - 93px)',
        monaco_small: 'calc(100vh - 129px)',
      },
      fontFamily: {
        sans: [
          'Optimistic Display',
          '-apple-system',
          ...defaultTheme.fontFamily.sans,
        ],
      },
    },
  },
  plugins: [

,
      width: {
        toast: 'min(900px, 100vw - 40px)',
        'toast-body': 'calc(100% - 60px)',
        'toast-title': 'calc(100% - 40px)',
      },
      height: {
        content: 'calc(100vh - 45px)',
        monaco: 'c


 MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

// https://github.com/reactjs/reactjs.org/blob/main/beta/src/components/Logo.tsx

export default function Logo(props: JSX.IntrinsicElements['svg']): JSX.Element {
  return (
    <svg
      viewBox="0 0 410 369"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
      {...props}>
      <path
        d="M204.995 224.552C226.56 224.552 244.042 207.07 244.042 185.506C244.042 163.941 226.56 146.459 204.995 146.459C1


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
import React, {
  startTransition,
  useId,
  unstable_ViewTransition as ViewTransition,
  unstable_addTransitionType as addTransitionType,
} from 'react';
import clsx from 'clsx';
import {TOGGLE_TAB_TRANSITION} from '../lib/transitionTypes';

export default function TabbedWindow({
  tabs,
  activeTab,
  onTabChange,
}: {
  tabs: Map<string, React.ReactNode>;
  activeTa

addTransitionType(TOGGLE_TAB_TRANSITION);
      onTabChange(tab);
    });
  };

  return (

b: string;
  onTabChange: (tab: string) => void;
}): React.ReactElement {
  const id = useId();
  const transitionName = `tab-highlight-${id}`;

  const handleTabChange = (tab: string): void => {
    startTransition(() => {


 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 {memo} from 'react';

export const IconChevron = memo<
  JSX.IntrinsicElements['svg'] & {
    /**
     * The direction the arrow should point.
     */
    displayDirection: 'right' | 'left';
  }
>(function IconChevron({className, displayDirection, ...props}) {
  const rotationClass =
    displayDirection === 'left' ? 'rotate-90' : '-rot

ate-90';
  const classes = className ? `${rotationClass} ${className}` : rotationClass;

  return (
    <svg
      className={classes}
      xmlns="http://www.w3.org/2000/svg"
      width="20"
      height="20"
      viewBox="0 0


p-simple.js
 *
 * Named lambdas (e.g. cb1) may be defined in the top scope of a function and
 * used in a different lambda (getArrMap1).
 *
 * Here, we should try to determine if cb1 is actually called. In this case:
 * - getArrMap1 is assumed to be called as it's passed to JSX
 * - cb1 is not assumed to be called since it's only used as a call operand
 */
function useFoo({arr1, arr2}) {
  const cb1 = e => arr1[0].value + e.value;
  const getArrMap1 = () => arr1.map(cb1);
  const cb2 = e => arr2[0].value +

 return (
    <Stringify
      getArrMap1={getArrMap1}
      getArrMap2={getArrMap2}
      shouldInvokeFns={true}
    />
  );
}

export const FIXTURE_ENTRYPOINT = {
  fn: useFoo,
  params: [{arr1: [], arr2: []}],
  sequentialRenders: [
    {arr1: [], arr2:

e.value;
  const getArrMap2 = () => arr1.map(cb2);


ort {Stringify, useIdentity} from 'shared-runtime';

/**
 * Here, the *inferred* dependencies of cb are `a` and `t1 = LoadContext capture x_@1`.
 * - t1 does not have a scope as it captures `x` after x's mutable range
 * - `x` is a context variable, which means its mutable range extends to all
 *    references / aliases.
 * - `a`, `b`, and `x` get the same mutable range due to potential aliasing.
 *
 * We currently bail out because `a` has a scope and is not transitively memoized
 * (as its scope is pruned

) {
  let x = useIdentity({val: 3});
  if (cond) {
    x = b;
  }

  const cb = useCallback(() => {
    return [a, x];
  }, [a, x]);

  return <Stringify cb={cb} shouldInvoke={true} />;
}

export const FIXTURE_ENTRYPOINT = {
  fn: useBar,
  params: [{a: 1,

due to a hook call)
 */
function useBar({a, b}, cond


 MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import {Resizable} from 're-resizable';
import React, {
  useId,
  unstable_ViewTransition as ViewTransition,
  unstable_addTransitionType as addTransitionType,
  startTransition,
} from 'react';
import {EXPAND_ACCORDION_TRANSITION} from '../lib/transitionTypes';

type TabsRecord = Map<string, React.ReactNode>;

export default function AccordionWindow(props: {
  defaultTab: string | null;
  tabs: TabsRecord;
  tabsOpen

     {Array.from(props.tabs.keys()).map(name => {
          return (
            <AccordionWindowItem
              name={name}
              key={name}
              tabs={props.tabs}
              tabsOpen={props.tabsOpen}
              setTabsOpen={prop

: Set<string>;
  setTabsOpen: (newTab: Set<string>) => void;
  changedPasses: Set<string>;
}): React.ReactElement {
  return (


oEditor, {loader, type Monaco} from '@monaco-editor/react';
import type {editor} from 'monaco-editor';
import * as monaco from 'monaco-editor';
import React, {
  useState,
  useRef,
  unstable_ViewTransition as ViewTransition,
  unstable_addTransitionType as addTransitionType,
  startTransition,
} from 'react';
import {Resizable} from 're-resizable';
import {useStore, useStoreDispatch} from '../StoreContext';
import {monacoConfigOptions} from './monacoOptions';
import {IconChevron} from '../Icons/IconChevro

const [isExpanded, setIsExpanded] = useState(false);

  // TODO: Add back <Activity> after upgrading next.js
  return (
    <>
      <div
        style={{
          display: isExpanded ? 'block' : 'none',
        }}>
        {/* <Activity mode={isExpanded

n';
import {CONFIG_PANEL_TRANSITION} from '../../lib/transitionTypes';

loader.config({monaco});

export default function ConfigEditor({
  formattedAppliedConfig,
}: {
  formattedAppliedConfig: string;
}): React.ReactElement {


 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 {render} from '@testing-library/react';
import * as React from 'react';

function Button({label}) {
  const theme = useTheme();
  const style = computeStyle(theme);
  return <button color={style}>{label}</button>;
}

let currentTheme = 'light';
function useTheme() {
  'use memo';
  return currentTheme;
}

let styleComputations = 0;
func

chInlineSnapshot(`
    <DocumentFragment>
      <button
        color="white"
      >
        Click me
      </button>
    </DocumentFragment>
  `);

  // Update the label, but not the theme
  rerender(<Button label="Click again" />);
  // `computeStyle` s

tion computeStyle(theme) {
  styleComputations++;
  return theme === 'light' ? 'white' : 'black';
}

test('update-button', () => {
  const {asFragment, rerender} = render(<Button label="Click me" />);
  expect(asFragment()).toMat


iates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import {
  CompilerErrorDetail,
  CompilerDiagnostic,
} from 'babel-plugin-react-compiler';
import {useDeferredValue, useMemo, useState} from 'react';
import {useStore} from '../StoreContext';
import ConfigEditor from './ConfigEditor';
import Input from './Input';
import {CompilerOutput, default as Output} from './Output';
import {compile} from '../../lib/compilation';

(
    () => compile(deferredStore.source, 'compiler', deferredStore.config),
    [deferredStore.source, deferredStore.config],
  );
  const [linterOutput] = useMemo(
    () => compile(deferredStore.source, 'linter', deferredStore.config),
    [deferredStor

import prettyFormat from 'pretty-format';

export default function Editor(): JSX.Element {
  const store = useStore();
  const deferredStore = useDeferredValue(store);
  const [compilerOutput, language, appliedOptions] = useMemo


ight (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.
 */

const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
const path = require('path');

const nextConfig = {
  experimental: {
    reactCompiler: true,
    viewTransition: true,
  },
  reactStrictMode: true,
  webpack: (config, options) => {
    // Load *.d.ts files as strings using https://webpack.js.org/guides/asset-

       languages: ['typescript', 'javascript'],
          filename: 'static/[name].worker.js',
        })
      );
    }

    config.resolve.alias = {
      ...config.resolve.alias,
      'react-compiler-runtime': path.resolve(
        __dirname,
        '

modules/#source-assets.
    config.module.rules.push({
      test: /\.d\.ts/,
      type: 'asset/source',
    });

    // Monaco Editor
    if (!options.isServer) {
      config.plugins.push(
        new MonacoWebpackPlugin({