 Promise(resolve => {
    setTimeout(resolve, timeoutMS);
  });
}

export default function FormActions() {
  const [textValue, setTextValue] = useState('0');
  const [radioValue, setRadioValue] = useState('two');
  const [checkboxValue, setCheckboxValue] = useState([false, true, true]);
  const [selectValue, setSelectValue] = useState('three');

  return (
    <form
      action={async () => {
        await defer(500);
      }}
      onReset={() => {
        setTextValue('0');
        setRadioValue('two');

         type="text"
            name="text"
            value={textValue}
            onChange={event => setTextValue(event.currentTarget.value)}
          />
        </fieldset>
        <fieldset style={{flexBasis: 0}}>
          <legend>type="radio"</le

        setCheckboxValue([false, true, true]);
        setSelectValue('three');
      }}>
      <div style={{display: 'flex'}}>
        <fieldset style={{flexBasis: 0}}>
          <legend>type="text"</legend>
          <input


traZeroes from './NumberInputExtraZeroes';

const React = window.React;

function NumberInputs() {
  return (
    <FixtureSet
      title="Number inputs"
      description="Number inputs inconsistently assign and report the value
                     property depending on the browser.">
      <TestCase
        title="Backspacing"
        description="The decimal place should not be lost">
        <TestCase.Steps>

Type "3.1"

Press backspace, eliminating the "1"

        <

Notes:</b> Modern Chrome and Safari {'<='} 6 clear trailing
          decimals on blur. React makes this concession so that the value
          attribute remains in sync with the value property.
        </p>
      </TestCase>

      <TestCase
        title

/TestCase.Steps>

        <TestCase.ExpectedResult>
          The field should read "3.", preserving the decimal place
        </TestCase.ExpectedResult>

        <NumberTestCase />

        <p className="footnote">
          <b>


alue: ''};
  _nestedDOMNode = null;
  _singleFormDOMNode = null;
  _multipleFormDOMNode = null;

  onChange = event => {
    this.setState({value: event.target.value});
  };

  resetSingleOptionForm = event => {
    event.preventDefault();
    this._singleFormDOMNode.reset();
  };

  resetMultipleOptionForm = event => {
    event.preventDefault();
    this._multipleFormDOMNode.reset();
  };

  componentDidMount() {
    this._renderNestedSelect();
  }

  componentDidUpdate() {
    this._renderNestedSelect();

="blue">Blue</option>
        <option value="green">Green</option>
      </select>,
      this._nestedDOMNode
    );
  }

  render() {
    return (
      <FixtureSet title="Selects">
        <form className="field-group">
          <fieldset>
            <

  }

  _renderNestedSelect() {
    ReactDOM.render(
      <select value={this.state.value} onChange={this.onChange}>
        <option value="">Select a color</option>
        <option value="red">Red</option>
        <option value


/../Fixture';

const React = window.React;

class ReplaceEmailInput extends React.Component {
  state = {
    formSubmitted: false,
  };

  onReset = () => {
    this.setState({formSubmitted: false});
  };

  onSubmit = event => {
    event.preventDefault();
    this.setState({formSubmitted: true});
  };

  render() {
    return (
      <Fixture>
        <form className="control-box" onSubmit={this.onSubmit}>
          <fieldset>
            <legend>Email</legend>
            {!this.state.formSubmitted ? (

 (
              <input type="text" disabled={true} />
            )}
          </fieldset>
        </form>
        <button type="button" onClick={this.onReset}>
          Reset
        </button>
      </Fixture>
    );
  }
}

export default ReplaceEmailIn

              <input type="email" />
            ) :


Set from '../../FixtureSet';
import TestCase from '../../TestCase';

const React = window.React;

class ProgressFixture extends React.Component {
  state = {value: 0, max: 1, enabled: false, backwards: false};

  startTest = () => {
    this.setState({enabled: true}, () => {
      this.progressIntervalId = setInterval(() => {
        if (this.state.backwards) {
          if (this.state.value > 0) {
            this.setState({value: this.state.value - this.state.max / 100});
          } else {
            if

lue < this.state.max) {
            this.setState({value: this.state.value + this.state.max / 100});
          } else {
            this.setState({backwards: true});
          }
        }
      }, 10);
    });
  };

  resetTest = () => {
    clearInterval(

 (this.state.max === 10000) {
              this.resetTest();
            } else {
              this.setState({max: this.state.max * 100, backwards: false});
            }
          }
        } else {
          if (this.state.va


nds React.Component {
  state = {value: ''};
  onChange = event => {
    this.setState({value: event.target.value});
  };
  render() {
    return (
      <Fixture>

{this.props.children}

          <fieldset>
            <legend>Controlled</legend>
            <input
              type="password"
              value={this.state.value}
              onChange={this.onChange}
            />

              {' '}

       </span>
          </fieldset>

          <fieldset>
            <legend>Uncontrolled</legend>
            <input type="password" defaultValue="" />
          </fieldset>
        </div>
      </Fixture>
    );
  }
}

export default PasswordTestCase;


estCase from '../../TestCase';
import JumpingCursorTestCase from './JumpingCursorTestCase';
import EmailEnabledAttributesTestCase from './EmailEnabledAttributesTestCase';
import EmailDisabledAttributesTestCase from './EmailDisabledAttributesTestCase';

const React = window.React;

function EmailInputs() {
  return (
    <FixtureSet title="Email inputs">
      <TestCase
        title="Spaces in email inputs"
        description={`
          Some browsers are trying to remove spaces from email inputs and afte

character</li>
        </TestCase.Steps>

        <TestCase.ExpectedResult>Cursor not moving.</TestCase.ExpectedResult>

        <JumpingCursorTestCase />
      </TestCase>

      <TestCase
        title="Attributes enabled"
        description={`

r
          doing this place cursor to the beginning.
        `}
        affectedBrowsers="Chrome">
        <TestCase.Steps>

Type space and character

Type character, space, character, delete last


const React = window.React;

export class CodeEditor extends React.Component {
  shouldComponentUpdate() {
    return false;
  }

  componentDidMount() {
    this.textarea = findDOMNode(this);

    // Important: CodeMirror incorrectly lays out the editor
    // if it executes before CSS has loaded
    // https://github.com/graphql/graphiql/issues/33#issuecomment-318188555
    Promise.all([
      import('codemirror'),
      import('codemirror/mode/jsx/jsx'),
      import('codemirror/lib/codemirror.css'),

r = CodeMirror.fromTextArea(this.textarea, {
      mode: 'jsx',
      theme: 'paraiso-dark',
      lineNumbers: true,
    });

    this.editor.on('change', function (doc) {
      onChange(doc.getValue());
    });
  }

  componentWillUnmount() {
    if (thi

     import('./codemirror-paraiso-dark.css'),
    ]).then(([CodeMirror]) => this.install(CodeMirror));
  }

  install(CodeMirror) {
    if (!this.textarea) {
      return;
    }

    const {onChange} = this.props;

    this.edito


re from '../../Fixture';
const React = window.React;

class ControlledFormFixture extends React.Component {
  constructor(props) {
    super(props);
    this.state = {name: '', email: ''};

    this.handleEmailChange = this.handleEmailChange.bind(this);
    this.handleNameChange = this.handleNameChange.bind(this);
  }

  handleEmailChange(event) {
    this.setState({email: event.target.value});
  }

  handleNameChange(event) {
    this.setState({name: event.target.value});
  }

  render() {
    return (

     x-autocompletetype="name"
            />
          </label>
          <br />
          <label>
            Email:
            <input
              type="text"
              value={this.state.email}
              onChange={this.handleEmailChange}

   <Fixture>
        <form>
          <label>
            Name:
            <input
              type="text"
              value={this.state.name}
              onChange={this.handleNameChange}
              name="name"


;

class DragBox extends React.Component {
  state = {
    hasCapture: false,
    circleLeft: 80,
    circleTop: 80,
  };
  isDragging = false;
  previousLeft = 0;
  previousTop = 0;

  onDown = event => {
    this.isDragging = true;
    event.target.setPointerCapture(event.pointerId);

    // We store the initial coordinates to be able to calculate the changes
    // later on.
    this.extractPositionDelta(event);
  };

  onMove = event => {
    if (!this.isDragging) {
      return;
    }
    const {left,

tCapture = event => this.setState({hasCapture: true});
  onLostCapture = event => this.setState({hasCapture: false});

  extractPositionDelta = event => {
    const left = event.pageX;
    const top = event.pageY;
    const delta = {
      left: left - thi

top} = this.extractPositionDelta(event);

    this.setState(({circleLeft, circleTop}) => ({
      circleLeft: circleLeft + left,
      circleTop: circleTop + top,
    }));
  };

  onUp = event => (this.isDragging = false);
  onGo


, y) {
  'use no forget';
  if (x != null) {
    x.value = (x.value ?? 0) + 1;
  }
  if (y != null) {
    y.value = (y.value ?? 0) + 1;
  }
}
function cond(x) {
  'use no forget';
  return x.value > 5;
}

function testFunction(props) {
  let a = {};
  let b = {};
  let c = {};
  let d = {};
  while (true) {
    let z = a;
    a = b;
    b = c;
    c = d;
    d = z;
    mutate(a, b);
    if (cond(a)) {
      break;
    }
  }

  // all of these tests are seemingly readonly, since the values are never directly

, which is later modified, and
  // these are therefore mutable references:
  if (a) {
  }
  if (b) {
  }
  if (c) {
  }
  if (d) {
  }

  mutate(d, null);
  return {a, b, c, d};
}

export const FIXTURE_ENTRYPOINT = {
  fn: testFunction,
  params: [{}],

// mutated again. but they are all aliased by `d`


e)) {
    x.value = [];
  }
  x.value.push(y);
  if (y != null) {
    y.value = x;
  }
}

function Component(props) {
  const a = {};
  const b = [a]; // array elements alias
  const c = {};
  const d = {c}; // object values alias

  // capture all the values into this object
  const x = {};
  x.b = b;
  const y = mutate(x, d); // mutation aliases the arg and return value

  // all of these tests are seemingly readonly, since the values are never directly
  // mutated again. but they are all aliased by `x`,

re mutable references:
  if (a) {
  }
  if (b) {
  }
  if (c) {
  }
  if (d) {
  }
  if (y) {
  }

  // could in theory mutate any of a/b/c/x/z, so the above should be inferred as mutable
  mutate(x, null);
  return x;
}

export const FIXTURE_ENTRYPOINT =

 which is later modified, and
  // these are therefo


This test fixture is similar to mutation-within-jsx. The only difference
 * is that there is no `freeze` effect here, which means that `z` may be
 * mutated after its memo block through mutating `y`.
 *
 * While this is technically correct (as `z` is a nested memo block), it
 * is an edge case as we believe that values are not mutated after their
 * memo blocks (which may lead to 'tearing', i.e. mutating one render's
 * values in a subsequent render.
 */
function useFoo({a, b}) {
  // x and y's scopes start

  // z captures the result of `mutate(y)`, which may be aliased to `y`.
  const z = [mutate(y)];
  // the following line may also mutate z
  mutate(y);
  // and end here
  return z;
}

export const FIXTURE_ENTRYPOINT = {
  fn: useFoo,
  params: [{a: 2, b:

 here
  const x = {a};
  const y = [b];
  mutate(x);


akeObject_Primitives,
  mutateAndReturn,
} from 'shared-runtime';

/**
 * In this example, the `<Stringify ... />` JSX block mutates then captures obj.
 * As JSX expressions freeze their values, we know that `obj` and `myDiv` cannot
 * be mutated past this.
 * This set of mutable range + scopes is an edge case because the JSX expression
 * references values in two scopes.
 * - (freeze) the result of `mutateAndReturn`
 *   this is a mutable value with a mutable range starting at `makeObject()`
 * - (mutate)

   $1@0 = mutate(obj@0);                   |
 *   myDiv@1 = JSX $1@0          <- scope@1  |
 * }                                         ⌟
 *
 * Coincidentally, the range of `obj` is extended by alignScopesToBlocks to *past*
 * the end of the JSX instructi

the lvalue storing the result of `<Stringify .../>`
 *   this is a immutable value and so gets assigned a different scope
 *
 * obj@0 = makeObj();                        ⌝ scope@0
 * if (cond) {                               |
 *


nctions

import {useCallback, useEffect} from 'react';
import {identity, Stringify, useIdentity} from 'shared-runtime';
import * as SharedRuntime from 'shared-runtime';

function Component(props) {
  function named() {
    const inner = () => props.named;
    const innerIdentity = identity(() => props.named);
    return inner(innerIdentity());
  }
  const callback = useCallback(() => {
    return 'ok';
  }, []);
  const namedVariable = function () {
    return props.namedVariable;
  };
  const methodCall =

namedElementAttr} />;
  const hookArgument = useIdentity(() => props.hookArgument);
  useEffect(() => {
    console.log(props.useEffect);
    JSON.stringify(null, null, () => props.useEffect);
    const g = () => props.useEffect;
    console.log(g());
  },

SharedRuntime.identity(() => props.methodCall);
  const call = identity(() => props.call);
  const builtinElementAttr = <div onClick={() => props.builtinElementAttr} />;
  const namedElementAttr = <Stringify onClick={() => props.


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

// derived from https://github.com/facebook/react/issues/32261
function Component({items}) {
  const record = useMemo(
    () =>
      Object.fromEntries(
        items.map(item => [item.id, ref => <Stringify ref={ref} {...item} />])
      ),
    [items]
  );

  // Without a declaration for Object.entries(), this would be assumed to mutate
  // `record`, meaning existing memoization couldn't be preserv

ap(id => (
        <Stringify key={id} render={record[id]} />
      ))}
    </div>
  );
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [
    {
      items: [
        {id: '0', name: 'Hello'},
        {id: '1', name: 'World!'},
      ],

ed
  return (
    <div>
      {Object.keys(record).m


gify} from 'shared-runtime';

// derived from https://github.com/facebook/react/issues/32261
function Component({items}) {
  const record = useMemo(
    () =>
      Object.fromEntries(
        items.map(item => [
          item.id,
          {id: item.id, render: ref => <Stringify ref={ref} {...item} />},
        ])
      ),
    [items]
  );

  // Without a declaration for Object.entries(), this would be assumed to mutate
  // `record`, meaning existing memoization couldn't be preserved
  return (
    <div>

(
        <Stringify key={id} render={render} />
      ))}
    </div>
  );
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [
    {
      items: [
        {id: '0', name: 'Hello'},
        {id: '1', name: 'World!'},
      ],
    },
  ],
};


;
  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}],
  sequentialRenders: [

rue, 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},
    {cond: false},
  ],
};


/ @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies

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

function Component({x}) {
  const object = useMemo(() => {
    return identity({
      callback: () => {
        return identity(x.y.z); // accesses more levels of properties than the manual memo
      },
    });
    // x.y as a manual dep only tells us that x is non-nullable, not that x.y is n

nput1 = {x: {y: {z: 42}}};
const input1b = {x: {y: {z: 42}}};
const input2 = {x: {y: {z: 3.14}}};
export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [input1],
  sequentialRenders: [
    input1,
    input1,
    input1b, // should reset even thou

on-nullable
    // we can only take a dep on x.y, not x.y.z
  }, [x.y]);
  const result = useMemo(() => {
    return [object.callback()];
  }, [object]);
  return <ValidateMemoization inputs={[x.y]} output={result} />;
}

const i


eserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies

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

function Component({x}) {
  const object = useMemo(() => {
    return identity({
      callback: () => {
        return identity(x.y.z);
      },
    });
  }, [x.y.z]);
  const result = useMemo(() => {
    return [object.callback()];
  }, [object]);
  return <ValidateMemoization inputs={[x.y.z]} output={r


 @enableOptionalDependencies

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

function Component({x, y, z}) {
  const object = useMemo(() => {
    return identity({
      callback: () => {
        return identity(x?.y?.z, y.a?.b, z.a.b?.c);
      },
    });
  }, [x?.y?.z, y.a?.b, z.a.b?.c]);
  const result = useMemo(() => {
    return [object.callback()];
  }, [object]);
  return <Inner x={x} result={result} />;
}

function Inner({x, result}) {
  'use no memo';

return <ValidateMemoization inputs={[x.y.z]} outpu


tion Component(props) {
  // a and b are independent but their mutations are interleaved, so
  // they get grouped in a reactive scope. this means that a becomes
  // reactive since it will effectively re-evaluate based on a reactive
  // input
  const a = [];
  const b = [];
  b.push(props.cond);
  a.push(false);

  // Downstream consumer of a, which initially seems non-reactive except
  // that a becomes reactive, per above
  const c = [a];

  let x = 0;
  do {
    x += 1;
  } while (c[0][0]);
  // The va

 of `x`
  // depends on the "control" value `c[0]` which becomes reactive via
  // being interleaved with `b`.
  // Therefore x should be treated as reactive too.
  return [x];
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{cond: true}

lues assigned to `x` are non-reactive, but the value


 Component(props) {
  // a and b are independent but their mutations are interleaved, so
  // they get grouped in a reactive scope. this means that a becomes
  // reactive since it will effectively re-evaluate based on a reactive
  // input
  const a = [];
  const b = [];
  b.push(props.cond);
  a.push({a: false});

  // Downstream consumer of a, which initially seems non-reactive except
  // that a becomes reactive, per above
  const c = [a];

  let x;
  for (const i in c[0][0]) {
    x = 1;
  }
  // The v

e of `x`
  // depends on the "control" value `c[0]` which becomes reactive via
  // being interleaved with `b`.
  // Therefore x should be treated as reactive too.
  return [x];
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{cond: true

alues assigned to `x` are non-reactive, but the valu


 Component(props) {
  // a and b are independent but their mutations are interleaved, so
  // they get grouped in a reactive scope. this means that a becomes
  // reactive since it will effectively re-evaluate based on a reactive
  // input
  const a = [];
  const b = [];
  b.push(props.cond);
  a.push(0);

  // Downstream consumer of a, which initially seems non-reactive except
  // that a becomes reactive, per above
  const c = [a];

  let x;
  for (let i = c[0][0]; i < 10; i++) {
    x = 1;
  }
  // The

ue of `x`
  // depends on the "control" value `c[0]` which becomes reactive via
  // being interleaved with `b`.
  // Therefore x should be treated as reactive too.
  return [x];
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{cond: tru

values assigned to `x` are non-reactive, but the val


ion Component(props) {
  // a and b are independent but their mutations are interleaved, so
  // they get grouped in a reactive scope. this means that a becomes
  // reactive since it will effectively re-evaluate based on a reactive
  // input
  const a = [];
  const b = [];
  b.push(props.cond);
  a.push(null);

  // Downstream consumer of a, which initially seems non-reactive except
  // that a becomes reactive, per above
  const c = [a];

  let x;
  for (const i of c[0]) {
    x = 1;
  }
  // The values

x`
  // depends on the "control" value `c[0]` which becomes reactive via
  // being interleaved with `b`.
  // Therefore x should be treated as reactive too.
  return [x];
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{cond: true}],
};

assigned to `x` are non-reactive, but the value of `


 Component(props) {
  // a and b are independent but their mutations are interleaved, so
  // they get grouped in a reactive scope. this means that a becomes
  // reactive since it will effectively re-evaluate based on a reactive
  // input
  const a = [];
  const b = [];
  b.push(props.cond);
  a.push(10);

  // Downstream consumer of a, which initially seems non-reactive except
  // that a becomes reactive, per above
  const c = [a];

  let x;
  for (let i = 0; i < c[0][0]; i++) {
    x = 1;
  }
  // The


 Component(props) {
  // a and b are independent but their mutations are interleaved, so
  // they get grouped in a reactive scope. this means that a becomes
  // reactive since it will effectively re-evaluate based on a reactive
  // input
  const a = [];
  const b = [];
  b.push(props.cond);
  a.push(10);

  // Downstream consumer of a, which initially seems non-reactive except
  // that a becomes reactive, per above
  const c = [a];

  let x;
  for (let i = 0; i < 10; i += c[0][0]) {
    x = 1;
  }
  //

 value of `x`
  // depends on the "control" value `c[0]` which becomes reactive via
  // being interleaved with `b`.
  // Therefore x should be treated as reactive too.
  return [x];
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{cond:

The values assigned to `x` are non-reactive, but the


 Component(props) {
  // a and b are independent but their mutations are interleaved, so
  // they get grouped in a reactive scope. this means that a becomes
  // reactive since it will effectively re-evaluate based on a reactive
  // input
  const a = [];
  const b = [];
  b.push(props.cond);
  a.push(null);

  // Downstream consumer of a, which initially seems non-reactive except
  // that a becomes reactive, per above
  const c = [a];

  let x;
  if (c[0][0]) {
    x = 1;
  } else {
    x = 2;
  }
  // T

value of `x`
  // depends on the "control" value `c[0]` which becomes reactive via
  // being interleaved with `b`.
  // Therefore x should be treated as reactive too.
  return [x];
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{cond:

he values assigned to `x` are non-reactive, but the


and b are independent but their mutations are interleaved, so
  // they get grouped in a reactive scope. this means that a becomes
  // reactive since it will effectively re-evaluate based on a reactive
  // input
  const a = [];
  const b = [];
  b.push(props.cond);
  a.push(null);

  // Downstream consumer of a, which initially seems non-reactive except
  // that a becomes reactive, per above
  const c = [a];

  let x;
  switch (c[0][0]) {
    case true: {
      x = 1;
      break;
    }
    default: {

 are non-reactive, but the value of `x`
  // depends on the "control" value `c[0]` which becomes reactive via
  // being interleaved with `b`.
  // Therefore x should be treated as reactive too.
  return [x];
}

export const FIXTURE_ENTRYPOINT = {
  fn: Co

    x = 2;
    }
  }
  // The values assigned to `x`


function Component(props) {
  // a and b are independent but their mutations are interleaved, so
  // they get grouped in a reactive scope. this means that a becomes
  // reactive since it will effectively re-evaluate based on a reactive
  // input
  const a = [];
  const b = [];
  b.push(props.cond);
  a.push(null);

  // Downstream consumer of a, which initially seems non-reactive except
  // that a becomes reactive, per above
  const c = [a];

  let x;
  while (c[0][0]) {
    x = 1;
  }
  // The values a

`
  // depends on the "control" value `c[0]` which becomes reactive via
  // being interleaved with `b`.
  // Therefore x should be treated as reactive too.
  return [x];
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{cond: true}],
};

ssigned to `x` are non-reactive, but the value of `x


PreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false
import {useMemo} from 'react';
import {ValidateMemoization, useHook} from 'shared-runtime';

function UnmemoizedCallbackCapturedInContextVariable({cond1, cond2}) {
  // The return value is captured by `x` which is a context variable, which
  // extends a's range to include the call instruction. This prevents the entire
  // range from being memoized
  const a = useHook();
  // Because b is also part of that same mutable

le
  let x;
  if (cond1) {
    x = a;
  } else if (cond2) {
    x = b;
  } else {
    return null;
  }

  const f = () => {
    return x;
  };
  const result = f();

  return <ValidateMemoization inputs={[cond1, cond2]} output={result} />;
}

export const

 range, it can't be memoized either
  const b = useMemo(() => ({}), []);

  // Conditional assignment without a subsequent mutation normally doesn't create a mutable
  // range, but in this case we're reassigning a context variab


'shared-runtime';

function Component(props) {
  let x;
  // Reassign `x` based on a reactive value, but inside a function expression
  // to make it a context variable
  const f = () => {
    if (props.cond) {
      x = 1;
    } else {
      x = 2;
    }
  };
  // Pass `f` through a function to prevent IIFE inlining optimizations
  const f2 = identity(f);
  f2();

  // The values assigned to `x` are non-reactive, but the value of `x`
  // depends on the "control" value `props.cond` which is reactive.
  //

urn [x];
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [],
  sequentialRenders: [
    {cond: true},
    {cond: true},
    {cond: false},
    {cond: false},
    {cond: true},
    {cond: false},
    {cond: true},
    {cond: false},
  ],
}

Therefore x should be treated as reactive too.
  ret


nction Component(props) {
  const [x, setX] = useState(false);
  const [y, setY] = useState(false);
  let setState;
  if (props.cond) {
    setState = setX;
  } else {
    setState = setY;
  }
  const setState2 = setState;
  const stateObject = {setState: setState2};
  return (
    <Foo
      cond={props.cond}
      setX={setX}
      setY={setY}
      setState={stateObject.setState}
    />
  );
}

function Foo({cond, setX, setY, setState}) {
  if (cond) {
    invariant(setState === setX, 'Expected the corre

State === setY, 'Expected the correct setState function');
  }
  return 'ok';
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [],
  sequentialRenders: [
    {cond: true},
    {cond: true},
    {cond: false},
    {cond: false},
    {cond:

ct setState function');
  } else {
    invariant(set


 value = null;
  loop: for (let i = 0; i < 10; i++) {
    switch (value) {
      case true: {
        x = 1;
        break loop;
      }
      case false: {
        x = 2;
        break loop;
      }
    }

    value = props.cond;
  }

  // The values assigned to `x` are non-reactive, but the value of `x`
  // depends on the "control" variable `value` used as the switch test
  // condition. That variable is initially null on the first iteration
  // of the loop, but is later set to `props.value` which is re

ve.
  return [x];
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [],
  sequentialRenders: [
    {cond: true},
    {cond: true},
    {cond: false},
    {cond: false},
    {cond: true},
    {cond: false},
    {cond: true},
    {cond: false

active.
  // Therefore x should be treated as reacti


mponent(props) {
  const x = [];
  const y = x;

  // y isn't reactive yet when we first visit this, so z is initially non-reactive
  const z = [y];

  // then we realize y is reactive. we need a fixpoint to propagate this back to z
  y.push(props.input);

  // PruneNonReactiveDependencies partially propagates reactivity (for now) which
  // we bypass with an indirection of storing into another variable
  const a = [z];

  // b's value is conditional on `a`, which is reactive per above
  let b = 0;
  if (a[

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [],
  sequentialRenders: [
    {input: 42},
    {input: 42},
    {input: 'sathya'},
    {input: 'sathya'},
    {input: 42},
    {input: 'sathya'},
    {input: 42},
    {input: 'sathya'},
  ],
}


 {Stringify} from 'shared-runtime';

function Component({config}) {
  /**
   * The original memoization is optimal in the sense that it has
   * one output (the object) and one dependency (`config`). Both
   * the `a` and `b` functions will have to be recreated whenever
   * `config` changes, cascading to update the object.
   *
   * However, we currently only consider consecutive scopes for
   * merging, so we first see the `a` scope, then the `b` scope,
   * and see that the output of the `a` scope is use

fig
   *            /      \
   *          [a]      [b]
   *           \       /
   *           [object]
   *
   * All the scopes (shown in []) are transitively dependent on
   * `config`, so they can be merged.
   */
  const object = useMemo(() => {
    c

d later -
   * so we don't merge these scopes, and so on.
   *
   * The more optimal thing would be to build a dependency graph
   * of scopes so that we can see the data flow is along the lines
   * of:
   *
   *             con


e';

/**
 * Example fixture demonstrating a case where we could hoist dependencies
 * and reuse them across scopes. Here we extract a temporary for `item.value`
 * and reference it both in the scope for `a`. Then the scope for `c` could
 * use `<item-value-temp>.inner` as its dependency, avoiding reloading
 * `item.value`.
 */
function Test({item, index}: {item: {value: {inner: any}}, index: number}) {
  // These scopes have the same dependency, `item.value`, and could
  // share a hoisted expression to eva

value: item.value, index});
  }
  const b = [item.value];

  // This dependency is more precise (nested property), the outer
  // `item.value` portion could use a hoisted dep for `item.value
  const c = [item.value.inner];
  return <Stringify value={[a, b,

luate it
  const a = [];
  if (index) {
    a.push({


ns:false @enableNewMutationAliasingModel
import {arrayPush, setPropertyByKey, Stringify} from 'shared-runtime';

/**
 * Repro of a bug fixed in the new aliasing model.
 *
 * 1. `InferMutableRanges` derives the mutable range of identifiers and their
 *     aliases from `LoadLocal`, `PropertyLoad`, etc
 *   - After this pass, y's mutable range only extends to `arrayPush(x, y)`
 *   - We avoid assigning mutable ranges to loads after y's mutable range, as
 *     these are working with an immutable value. As a r

 infer that
 *     - `arrayPush(y, x)` might alias `x` and `y` to each other
 *     - `setPropertyKey(x, ...)` may mutate both `x` and `y`
 *   - This pass correctly extends the mutable range of `y`
 *   - Since we didn't run `InferMutableRange` logic agai

esult, `LoadLocal y` and
 *     `PropertyLoad y` do not get mutable ranges
 * 2. `InferReactiveScopeVariables` extends mutable ranges and creates scopes,
 *    as according to the 'co-mutation' of different values
 *   - Here, we


fy} from 'shared-runtime';

// This is a translation of the original merge-consecutive-scopes which uses plain objects
// to describe the UI instead of JSX. The JSXText elements in that fixture happen to
// prevent scome scopes from merging, which concealed a bug with the merging logic.
// By avoiding JSX we eliminate extraneous instructions and more accurately test the merging.
function Component(props) {
  let [state, setState] = useState(0);
  return [
    {component: Stringify, props: {text: 'Counter'}}

},
    {
      component: 'button',
      props: {
        'data-testid': 'button',
        onClick: () => setState(state + 1),
        children: ['increment'],
      },
    },
  ];
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{}],
};

,
    {component: 'span', props: {children: [state]}


reSet from '../../FixtureSet';
import TestCase from '../../TestCase';

const React = window.React;
const ReactDOM = window.ReactDOM;

const supportsCustomElements = typeof customElements !== 'undefined';

class HelloWorld extends React.Component {
  render() {
    return
Hello, world!
;
  }
}

if (supportsCustomElements) {
  // Babel breaks web components.
  // https://github.com/w3c/webcomponents/issues/587
  // eslint-disable-next-line no-new-func
  const MyElement = new Function(
    'React',

nt(HelloWorld), shadowRoot);
      }
    }`
  )(React, ReactDOM, HelloWorld);
  customElements.define('my-element', MyElement);
}

export default class ButtonTestCases extends React.Component {
  render() {
    return (
      <FixtureSet
        title="Cus

 'ReactDOM',
    'HelloWorld',
    `
    return class MyElement extends HTMLElement {
      constructor() {
        super();
        const shadowRoot = this.attachShadow({ mode:'open' });
        ReactDOM.render(React.createEleme


 {Stringify, graphql} from 'shared-runtime';

function useFragment(_arg1, _arg2) {
  'use no forget';
  return {
    urls: ['url1', 'url2', 'url3'],
    comments: ['comment1'],
  };
}

function Component(props) {
  const post = useFragment(
    graphql`
      fragment F on T {
        id
      }
    `,
    props.post
  );
  const allUrls = [];
  // `media` and `urls` are exported from the scope that will wrap this code,
  // but `comments` is not (it doesn't need to be memoized, bc the callback
  // only ch

his means we try to
  // reassign `comments` when there's no declaration for it.
  const {media = null, comments = [], urls = []} = post;
  const onClick = e => {
    if (!comments.length) {
      return;
    }
    console.log(comments.length);
  };
  allU

ecks `comments.length`)
  // because of the scope, the let declaration for media and urls are lifted
  // out of the scope, and the destructure statement ends up turning into
  // a reassignment, instead of a const declaration. t


shared-runtime';

// Achieving Forget's level of memoization precision in this example isn't possible with useMemo
// without significantly altering the code, so disable the non-Forget evaluation of this fixture.
// @disableNonForgetInSprout
function Component({a, b, c}) {
  const x = [];
  let y;
  if (a) {
    y = [b];
  }
  x.push(c);

  // this scope should not merge with the above scope because y does not invalidate
  // on changes to `c`
  const z = [y];

  // return [x, z];
  return (
    <>
      <V

      <ValidateMemoization inputs={[a, b]} output={z} />
    </>
  );
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{a: false, b: null, c: 0}],
  sequentialRenders: [
    {a: false, b: null, c: 0},
    {a: false, b: null, c: 1},
    {a

alidateMemoization inputs={[a, b, c]} output={x} />


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

function Foo() {
  /**
   * Previously, this lowered to
   * $1 = LoadContext capture setState
   * $2 = FunctionExpression deps=$1 context=setState
   *  [[ at this point, we freeze the `LoadContext setState` instruction, but it will never be referenced again ]]
   *
   * Now, this function expression directly references `setState`, which freezes
   * the source `DeclareContext HoistedConst setState`. Freezing source identifiers
   * (instead of the one le

ect
   * for everything *other* than hoisted context declarations.
   *
   * $2 = Function context=setState
   */
  useEffect(() => setState(2), []);

  const [state, setState] = useState(0);
  return <Stringify state={state} />;
}

export const FIXTURE_EN

vel removed `LoadContext`) is more semantically corr


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

function Component({prop1, prop2}) {
  'use memo';

  const data = useIdentity(
    new Map([
      [0, 'value0'],
      [1, 'value1'],
    ])
  );
  let i = 0;
  const items = [];
  items.push(
    <Stringify
      key={i}
      onClick={() => data.get(i) + prop1}
      shouldInvokeFns={true}
    />
  );
  i = i + 1;
  items.push(
    <Stringify
      key={i}
      onClick={() => data.get(i) + prop2}
      shouldInvokeFns={true}
    />
  );

tems}</>;
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{prop1: 'prop1', prop2: 'prop2'}],
  sequentialRenders: [
    {prop1: 'prop1', prop2: 'prop2'},
    {prop1: 'prop1', prop2: 'prop2'},
    {prop1: 'changed', prop2: 'prop2'},
  ],


 {useEffect} from 'react';

function Component() {
  let local;

  const reassignLocal = newValue => {
    local = newValue;
  };

  const onMount = newValue => {
    reassignLocal('hello');

    if (local === newValue) {
      // Without React Compiler, `reassignLocal` is freshly created
      // on each render, capturing a binding to the latest `local`,
      // such that invoking reassignLocal will reassign the same
      // binding that we are observing in the if condition, and
      // we reach this br

assignLocal` will reassign the wrong
      // version of `local`, and not update the binding we are checking
      // in the if condition.
      //
      // To protect against this, we disallow reassigning locals from
      // functions that escape
      t

anch
      console.log('`local` was updated!');
    } else {
      // With React Compiler enabled, `reassignLocal` is only created
      // once, capturing a binding to `local` in that render pass.
      // Therefore, calling `re


ction Component() {
  let local;

  const reassignLocal = newValue => {
    local = newValue;
  };

  const onClick = newValue => {
    reassignLocal('hello');

    if (local === newValue) {
      // Without React Compiler, `reassignLocal` is freshly created
      // on each render, capturing a binding to the latest `local`,
      // such that invoking reassignLocal will reassign the same
      // binding that we are observing in the if condition, and
      // we reach this branch
      console.log('`local`

wrong
      // version of `local`, and not update the binding we are checking
      // in the if condition.
      //
      // To protect against this, we disallow reassigning locals from
      // functions that escape
      throw new Error('`local` not upd

 was updated!');
    } else {
      // With React Compiler enabled, `reassignLocal` is only created
      // once, capturing a binding to `local` in that render pass.
      // Therefore, calling `reassignLocal` will reassign the


ingMemoizationGuarantees:false

/**
 * 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
 *
 * When we validate preserving manual memoization we incorrectly reject this, because
 * the original memoization had `object` depending on `input` but our scope depends on
 * `value`.
 *
 * This fixture adds a later potenti

ail validation. This confirms that even though we allow the dependency to diverge,
 * we still check that the output value is memoized.
 */
function useInputValue(input) {
  const object = React.useMemo(() => {
    const {value} = transform(input);
    ret

al mutation, which extends the scope and should
 * f


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

function Component() {
  const data = useIdentity(
    new Map([
      [0, 'value0'],
      [1, 'value1'],
    ])
  );
  const items = [];
  // NOTE: `i` is a context variable because it's reassigned and also referenced
  // within a closure, the `onClick` handler of each item
  // TODO: for loops create a unique environment on each iteration, which means
  // that if the iteration variable is only updated in the updater, the variable
  // is effective

 {
    items.push(
      <Stringify key={i} onClick={() => data.get(i)} shouldInvokeFns={true} />
    );
  }
  return <>{items}</>;
}

const MIN = 0;
const MAX = 3;
const INCREMENT = 1;

export const FIXTURE_ENTRYPOINT = {
  params: [],
  fn: Component,
};

ly const within the body and the "update" acts more like
  // a re-initialization than a reassignment.
  // Until we model this "new environment" semantic, we allow this case to error
  for (let i = MIN; i <= MAX; i += INCREMENT)


eserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies

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

function Component({x}) {
  const object = useMemo(() => {
    return identity({
      callback: () => {
        // This is a bug in our dependency inference: we stop capturing dependencies
        // after x.a.b?.c. But what this dependency is telling us is that if `x.a.b`
        // was non-nullish, the

e]);
  const result = useMemo(() => {
    return [object.callback()];
  }, [object]);
  return <Inner x={x} result={result} />;
}

function Inner({x, result}) {
  'use no memo';
  return <ValidateMemoization inputs={[x.y.z]} output={result} />;
}

export c

n we can access `.c.d?.e`. Thus we should take the
        // full property chain, exactly as-is with optionals/non-optionals, as a
        // dependency
        return identity(x.a.b?.c.d?.e);
      },
    });
  }, [x.a.b?.c.d?.


eExistingMemoizationGuarantees:false
import {useMemo} from 'react';
import {logValue, useFragment, useHook, typedLog} from 'shared-runtime';

component Component() {
  const data = useFragment();

  const getIsEnabled = () => {
    if (data != null) {
      return true;
    } else {
      return {};
    }
  };

  // We infer that getIsEnabled returns a mutable value, such that
  // isEnabled is mutable
  const isEnabled = useMemo(() => getIsEnabled(), [getIsEnabled]);

  // We then infer getLoggingData as c

is function are then inferred as extending
  // the mutable range of isEnabled
  const getLoggingData = () => {
    return {
      isEnabled,
    };
  };

  // The call here is then inferred as an indirect mutation of isEnabled
  useHook(getLoggingData());

apturing that mutable value,
  // so any calls to th


ot mutated later
  // but a is a dependnecy of b, which is a dependency of c.
  // we have to memoize a to avoid breaking memoization of b,
  // to avoid breaking memoization of c.
  const a = [props.a];

  // a can be independently memoized, is not mutated later,
  // but is a dependency of d which is part of c's scope.
  // we have to memoize b to avoid breaking memoization of c.
  const b = [a];

  // c and d are interleaved and grouped into a single scope,
  // but they are independent values. d does no

zed or else b will invalidate
  // on every render since a is a dependency. we also need to
  // ensure that a is memoized, since it's a dependency of b.
  const c = [];
  const d = {};
  d.b = b;
  c.push(props.b);

  return c;
}

export const FIXTURE_ENT

t escape, but
  // we need to ensure that b is memoi


ionMode:"infer" @enableResetCacheOnSourceFileChanges @validateExhaustiveMemoizationDependencies:false
import {useEffect, useMemo, useState} from 'react';
import {ValidateMemoization} from 'shared-runtime';

let pretendConst = 0;

function unsafeResetConst() {
  pretendConst = 0;
}

function unsafeUpdateConst() {
  pretendConst += 1;
}

function Component() {
  useState(() => {
    // unsafe: reset the constant when first rendering the instance
    unsafeResetConst();
  });
  // UNSAFE! changing a module var

 should
  // reset on changes to globals that impact the component/hook, effectively memoizing
  // as if value was reactive. However, we don't want to actually treat globals as
  // reactive (though that would be trivial) since it could change compilation

iable that is read by a component is normally
  // unsafe, but in this case we're simulating a fast refresh between each render
  unsafeUpdateConst();

  // TODO: In fast refresh mode (@enableResetCacheOnSourceFileChanges) Forget


f function expressions,
 * regardless of control flow. This is simply because we wrote support for
 * function expressions before doing a lot of work in PropagateScopeDeps
 * to handle conditionally accessed dependencies.
 *
 * Current evaluator error:
 *  Found differences in evaluator results
 *  Non-forget (expected):
 *  (kind: ok) <div>{"shouldInvokeFns":true,"callback":{"kind":"Function","result":null}}</div>
 *  Forget:
 *  (kind: exception) Cannot read properties of null (reading 'prop')
 */
functio

) => {
    if (!isObjNull) {
      return obj.prop;
    } else {
      return null;
    }
  };
  return <Stringify shouldInvokeFns={true} callback={callback} />;
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{obj: null, isObjNull: true

n Component({obj, isObjNull}) {
  const callback = (


@loggerTestOnly
import {createContext, use, useState} from 'react';
import {
  Stringify,
  identity,
  makeObject_Primitives,
  useHook,
} from 'shared-runtime';

function Component() {
  const w = use(Context);

  // The scopes for x and x2 are interleaved, so this is one scope with two values
  const x = makeObject_Primitives();
  const x2 = makeObject_Primitives();
  useState(null);
  identity(x);
  identity(x2);

  // We create a scope for all call expressions, but prune those with hook calls
  // in t

s();
    z.push(obj);
  }

  // Overall we expect two pruned scopes (for x+x2, and obj), with 3 pruned scope values.
  return <Stringify items={[w, x, x2, y, z]} />;
}

const Context = createContext();

function Wrapper() {
  return (
    <Context value={4

his case it's _just_ a hook call, so we don't count this as pruned
  const y = useHook();

  const z = [];
  for (let i = 0; i < 10; i++) {
    // The scope for obj is pruned bc it's in a loop
    const obj = makeObject_Primitive


dentity,
  makeArray,
  Stringify,
  useFragment,
} from 'shared-runtime';

/**
 * Bug repro showing why it's invalid for function references to be annotated
 * with a `Read` effect when that reference might lead to the function being
 * invoked.
 *
 * Note that currently, `Array.map` is annotated to have `Read` effects on its
 * operands. This is incorrect as function effects must be replayed when `map`
 * is called
 * - Read:                non-aliasing data dependency
 * - Capture:             maybe-alia

sing data dependency
 * - ConditionallyMutate: maybe-aliasing data dependency; maybe-write / invoke
 *     but only if the value is mutable
 *
 * Invalid evaluator result: Found differences in evaluator results Non-forget
 * (exp


eserveExistingMemoizationGuarantees:false
import {Stringify, identity} from 'shared-runtime';

function foo() {
  try {
    identity(`${Symbol('0')}`); // Uncaught TypeError: Cannot convert a Symbol value to a string (leave as is)
  } catch {}

  return (
    <Stringify
      value={[
        `` === '',
        `\n` === '\n',
        `a\nb`,
        `\n`,
        `a${1}b`,
        ` abc \u0041\n\u000a\ŧ`,
        `abc${1}def`,
        `abc${1}def${2}`,
        `abc${1}def${2}ghi`,
        `a${1 + 3}b${``}c$

{'d' + `e${2 + 4}f`}`,
        `1${2}${Math.sin(0)}`,
        `${NaN}`,
        `${Infinity}`,
        `${-Infinity}`,
        `${Number.MAX_SAFE_INTEGER}`,
        `${Number.MIN_SAFE_INTEGER}`,
        `${Number.MAX_VALUE}`,


untime';

function Component(props) {
  const post = useFragment(
    graphql`
      fragment F on T {
        id
      }
    `,
    props.post
  );
  const allUrls = [];
  // `media` and `urls` are exported from the scope that will wrap this code,
  // but `comments` is not (it doesn't need to be memoized, bc the callback
  // only checks `comments.length`)
  // because of the scope, the let declaration for media and urls are lifted
  // out of the scope, and the destructure statement ends up turning into

 this means we try to
  // reassign `comments` when there's no declaration for it.
  const {media, comments, urls} = post;
  const onClick = e => {
    if (!comments.length) {
      return;
    }
    console.log(comments.length);
  };
  allUrls.push(...url

// a reassignment, instead of a const declaration.


ffect} from 'react';
function Component() {
  let local;
  const mk_reassignlocal = () => {
    // Create the reassignment function inside another function, then return it
    const reassignLocal = newValue => {
      local = newValue;
    };
    return reassignLocal;
  };
  const reassignLocal = mk_reassignlocal();
  const onMount = newValue => {
    reassignLocal('hello');
    if (local === newValue) {
      // Without React Compiler, `reassignLocal` is freshly created
      // on each render, capturing a

!');
    } else {
      // With React Compiler enabled, `reassignLocal` is only created
      // once, capturing a binding to `local` in that render pass.
      // Therefore, calling `reassignLocal` will reassign the wrong
      // version of `local`, and

 binding to the latest `local`,
      // such that invoking reassignLocal will reassign the same
      // binding that we are observing in the if condition, and
      // we reach this branch
      console.log('`local` was updated


onAliasingModel @enablePreserveExistingMemoizationGuarantees:false
/**
 * This hook returns a function that when called with an input object,
 * will return the result of mapping that input with the supplied map
 * function. Results are cached, so if the same input is passed again,
 * the same output object will be returned.
 *
 * Note that this technically violates the rules of React and is unsafe:
 * hooks must return immutable objects and be pure, and a function which
 * captures and mutates a value when

eturnedFunction(someInput)`
 * strictly depends on `returnedFunction` and `someInput`, and cannot
 * otherwise change over time.
 */
hook useMemoMap<TInput: interface {}, TOutput>(
  map: TInput => TOutput
): TInput => TOutput {
  return useMemo(() => {

 called is inherently not pure.
 *
 * However, in this case it is technically safe _if_ the mapping function
 * is pure *and* the resulting objects are never modified. This is because
 * the function only caches: the result of `r


ction foo([a, b], {c, d, e = 'e'}, f = 'f', ...args) {
  let i = 0;
  var x = [];

  class Bar {
    #secretSauce = 42;
    constructor() {
      console.log(this.#secretSauce);
    }
  }

  const g = {b() {}, c: () => {}};
  const {z, aa = 'aa'} = useCustom();

  <Button haha={1}></Button>;
  <Button>{/** empty */}</Button>;

  const j = function bar([quz, qux], ...args) {};

  for (; i < 3; i += 1) {
    x.push(i);
  }
  for (; i < 3; ) {
    break;
  }
  for (;;) {
    break;
  }

  graphql`
    ${g}
  `

eIdentifier.y++;
  updateIdentifier.y--;

  switch (i) {
    case 1 + 1: {
    }
    case foo(): {
    }
    case x.y: {
    }
    default: {
    }
  }

  function component(a) {
    // Add support for function declarations once we support `var` hoisting.

;

  graphql`\\t\n`;

  for (c of [1, 2]) {
  }
  for ([v] of [[1], [2]]) {
  }
  for ({v} of [{v: 1}, {v: 2}]) {
  }

  for (let x in {a: 1}) {
  }

  let updateIdentifier = 0;
  --updateIdentifier;
  ++updateIdentifier;
  updat


@flow @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import {useFragment} from 'react-relay';
import LogEvent from 'LogEvent';
import {useCallback, useMemo} from 'react';

component Component(id) {
  const items = useFragment();

  const [index, setIndex] = useState(0);

  const logData = useMemo(() => {
    const item = items[index];
    return {
      key: item.key,
    };
  }, [index, items]);

  const set

ogData` may be mutated.
      LogEvent.log(() => object);
      setIndex(index);
    },
    [index, logData, items]
  );

  if (prevId !== id) {
    setCurrentIndex(0);
  }

  return (
    <Foo
      index={index}
      items={items}
      current={mediaLi

CurrentIndex = useCallback(
    (index: number) => {
      const object = {
        tracking: logData.key,
      };
      // We infer that this may mutate `object`, which in turn aliases
      // data from `logData`, such that `l


const TOTAL = 10;
function Component(props) {
  const items = [];
  for (let i = props.start ?? 0; i < props.items.length; i++) {
    const item = props.items[i];
    items.push(
{item.value}
);
  }
  return
{items}
;
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [
    {
      start: null,
      items: [
        {id: 0, value: 'zero'},
        {id: 1, value: 'one'},
      ],
    },
  ],
  sequentialRenders: [
    {
      start: 1,
      items: [
        {

  {id: 0, value: 'zero'},
        {id: 1, value: 'one'},
        {id: 2, value: 'two'},
      ],
    },
    {
      start: 1,
      items: [
        {id: 0, value: 'zero'},
        {id: 1, value: 'one'},
        {id: 2, value: 'two'},
      ],
    },
  ],

id: 0, value: 'zero'},
        {id: 1, value: 'one'},
      ],
    },
    {
      start: 2,
      items: [
        {id: 0, value: 'zero'},
        {id: 1, value: 'one'},
      ],
    },
    {
      start: 0,
      items: [


 {Throw} from 'shared-runtime';

/**
 * Note: this is disabled in the evaluator due to different devmode errors.
 * Found differences in evaluator results
 *  Non-forget (expected):
 *  (kind: ok) <invalidtag val="[object Object]"></invalidtag>
 *  logs: ['Warning: <%s /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.%s','invalidTag']
 *
 *  Forget:
 *  (kind: ok) <invalidtag val="[object Object]"></invalidtag>
 *  logs: [
 *   'Warning: <%s /> is using incor

rcase letter.%s','invalidTag',
 *  ]
 */
function useFoo() {
  const invalidTag = Throw;
  /**
   * Need to be careful to not parse `invalidTag` as a localVar (i.e. render
   * Throw). Note that the jsx transform turns this into a string tag:
   * `jsx("in

rect casing. Use PascalCase for React components, or lowercase for HTML elements.%s','invalidTag',
 *   'Warning: The tag <%s> is unrecognized in this browser. If you meant to render a React component, start its name with an uppe


Array} from 'shared-runtime';

/**
 * This fixture tests what happens when a reactive has no declarations (other than an early return),
 * no reassignments, and no dependencies. In this case the only thing we can use to decide if we
 * should take the if or else branch is the early return declaration. But if that uses the same
 * sentinel as the memo cache sentinel, then if the previous execution did not early return it will
 * look like we didn't execute the memo block yet, and we'll needlessly re-execute

that the scope for `x` only executes once, on the first render of the component.
 */
let ENABLE_FEATURE = false;

function Component(props) {
  let x = [];
  if (ENABLE_FEATURE) {
    x.push(42);
    return x;
  } else {
    console.log('fallthrough');
  }

instead of skipping
 * to the else branch.
 *
 * We have to use a distinct sentinel for the early return value.
 *
 * Here the fixture will always take the "else" branch and never early return. Logging (not included)
 * confirms


lidatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false

import {identity, Stringify, useHook} 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
 *
 * When we validate preserving manual memoization we incorrectly reject this, because
 * the origi

ization of `value`. This gets correctly flagged since
  // the dependency is being mutated
  let x = {};
  useHook();
  const object = React.useMemo(() => {
    const {value} = identity(input, x);
    return {value};
  }, [input, x]);
  return object;
}

f

nal memoization had `object` depending on `input` but our scope depends on
 * `value`.
 */
function useInputValue(input) {
  // Conflate the `identity(input, x)` call with something outside the useMemo,
  // to try and break memo


teMemoization} from 'shared-runtime';

let pretendConst = 0;

function unsafeResetConst() {
  pretendConst = 0;
}

function unsafeUpdateConst() {
  pretendConst += 1;
}

function Component() {
  useState(() => {
    // unsafe: reset the constant when first rendering the instance
    unsafeResetConst();
  });
  // UNSAFE! changing a module variable that is read by a component is normally
  // unsafe, but in this case we're simulating a fast refresh between each render
  unsafeUpdateConst();

  // In producti

mo caches are not
  // reset unless the deps change
  const value = useMemo(() => [{pretendConst}], []);

  return <ValidateMemoization inputs={[]} output={value} />;
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{}],
  sequentialRende

on mode (no @enableResetCacheOnSourceFileChanges) me


@flow @enableTransitivelyFreezeFunctionExpressions:false @enableNewMutationAliasingModel
import {setPropertyByKey, Stringify} from 'shared-runtime';

/**
 * Variation of bug in `bug-aliased-capture-aliased-mutate`.
 * Fixed in the new inference model.
 *
 * Found differences in evaluator results
 * Non-forget (expected):
 *   (kind: ok)
 *
{"cb":{"kind":"Function","result":2},"shouldInvokeFns":true}

 *
{"cb":{"kind":"Function","result":3},"shouldInvokeFns":true}

 * Forget:
 *   (ki

];
  const obj = {value: a};

  setPropertyByKey(obj, 'arr', arr);
  const obj_alias = obj;
  const cb = () => obj_alias.arr.length;
  for (let i = 0; i < a; i++) {
    arr.push(i);
  }
  return <Stringify cb={cb} shouldInvokeFns={true} />;
}

export const

nd: ok)
 *
{"cb":{"kind":"Function","result":2},"shouldInvokeFns":true}

 *
{"cb":{"kind":"Function","result":2},"shouldInvokeFns":true}

 */

function useFoo({a}: {a: number, b: number}) {
  const arr = [


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

function Content() {
  const [announcement, setAnnouncement] = useState('');
  const [users, setUsers] = useState([{name: 'John Doe'}, {name: 'Jane Doe'}]);

  // This was originally passed down as an onClick, but React Compiler's test
  // evaluator doesn't yet support events outside of React
  useEffect(() => {
    if (users.length === 2) {
      let removedUserName = '';
      setUsers(prevUsers => {
        const newUsers = [...prevUsers];

ewUsers.pop();
        return newUsers;
      });

      setAnnouncement(`Removed user (${removedUserName})`);
    }
  }, [users]);

  return <Stringify users={users} announcement={announcement} />;
}

export const FIXTURE_ENTRYPOINT = {
  fn: Content,
  p

   removedUserName = newUsers.at(-1).name;
        n


ow @compilationMode:"infer"
'use strict';

function getWeekendDays(user) {
  return [0, 6];
}

function getConfig(weekendDays) {
  return [1, 5];
}

component Calendar(user, defaultFirstDay, currentDate, view) {
  const weekendDays = getWeekendDays(user);
  let firstDay = defaultFirstDay;
  let daysToDisplay = 7;
  if (view === 'week') {
    let lastDay;
    // this assignment produces invalid code
    [firstDay, lastDay] = getConfig(weekendDays);
    daysToDisplay = ((7 + lastDay - firstDay) % 7) + 1;
  }

r: {},
      defaultFirstDay: 1,
      currentDate: {getDayOfWeek: () => 3},
      view: 'week',
    },
  ],
  sequentialRenders: [
    {
      user: {},
      defaultFirstDay: 1,
      currentDate: {getDayOfWeek: () => 3},
      view: 'week',
    },
    {

else if (view === 'day') {
    firstDay = currentDate.getDayOfWeek();
    daysToDisplay = 1;
  }

  return [currentDate, firstDay, daysToDisplay];
}

export const FIXTURE_ENTRYPOINT = {
  fn: Calendar,
  params: [
    {
      use


@enableNewMutationAliasingModel
import {CONST_TRUE, Stringify, mutate, useIdentity} from 'shared-runtime';

/**
 * Fixture showing an edge case for ReactiveScope variable propagation.
 * Fixed in the new inference model
 *
 * Found differences in evaluator results
 *   Non-forget (expected):
 *
{"obj":{"inner":{"value":"hello"},"wat0":"joe"},"inner":["[[ cyclic ref *2 ]]"]}

 *
{"obj":{"inner":{"value":"hello"},"wat0":"joe"},"inner":["[[ cyclic ref *2 ]]"]}

 *   Forget:
 *
{"

ll;
  const boxedInner = [obj?.inner];
  useIdentity(null);
  mutate(obj);
  if (boxedInner[0] !== obj?.inner) {
    throw new Error('invariant broken');
  }
  return <Stringify obj={obj} inner={boxedInner} />;
}

export const FIXTURE_ENTRYPOINT = {
  fn:

obj":{"inner":{"value":"hello"},"wat0":"joe"},"inner":["[[ cyclic ref *2 ]]"]}</div>
 *   [[ (exception in render) Error: invariant broken ]]
 *
 */
function Component() {
  const obj = CONST_TRUE ? {inner: {value: 'hello'}} : nu


/ @flow @enableAssumeHooksFollowRulesOfReact
function Component({label, highlightedItem}) {
  const serverTime = useServerTime();
  const highlight = new Highlight(highlightedItem);

  const time = serverTime.get();
  // subtle bit here: the binary expression infers the result of the call
  // as a primitive and not needing memoization. the logical is necessary
  // because without it there are no intermediate scopes which observe
  // the result of the binary expression, so its memoization can be pruned

be a constant value from the server
    },
  };
}

class Highlight {
  constructor(value) {
    this.value = value;
  }

  render() {
    return this.value;
  }
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{label: '<unused>', highligh

const timestampLabel = time / 1000 || label;

  return (
    <>
      {highlight.render()}
      {timestampLabel}
    </>
  );
}

function useServerTime() {
  'use no forget';

  return {
    get() {
      return 42000; // would


mport TestCase from '../../TestCase';
import HitBox from './hit-box';

const React = window.React;

class MouseMove extends React.Component {
  state = {
    events: [],
  };

  checkEvent = event => {
    let {events} = this.state;

    if (event.type === 'mousemove' && events.indexOf(event) === -1) {
      this.setState({events: events.concat(event)});
    }
  };

  render() {
    const {events} = this.state;

    return (
      <TestCase title="Mouse Move" description="">
        <TestCase.Steps>

       <HitBox onMouseMove={this.checkEvent} />

        <p>
          Was the event pooled?{' '}
          <b>
            {events.length ? (events.length <= 1 ? 'Yes' : 'No') : 'Unsure'} (
            {events.length} events)
          </b>
        </p>

Mouse over the box below

        </TestCase.Steps>

        <TestCase.ExpectedResult>
          Mousemove should share the same instance of the event between
          dispatches.
        </TestCase.ExpectedResult>


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

function Component({a, b, c}) {
  const map = new WeakMap();
  const mapAlias = map.set(a, 0);
  mapAlias.set(c, 0);

  const hasB = map.has(b);

  return (
    <>
      <ValidateMemoization
        inputs={[a, c]}
        output={map}
        onlyCheckCompiled={true}
      />
      <ValidateMemoization
        inputs={[a, c]}
        output={mapAlias}
        onlyCheckCompiled={true}
      />
      <ValidateMemoization

    inputs={[b]}
        output={[hasB]}
        onlyCheckCompiled={true}
      />
    </>
  );
}

const v1 = {value: 1};
const v2 = {value: 2};
const v3 = {value: 3};
export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params


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

function Component({a, b, c}) {
  const set = new WeakSet();
  const setAlias = set.add(a);
  setAlias.add(c);

  const hasB = set.has(b);

  return (
    <>
      <ValidateMemoization
        inputs={[a, c]}
        output={set}
        onlyCheckCompiled={true}
      />
      <ValidateMemoization
        inputs={[a, c]}
        output={setAlias}
        onlyCheckCompiled={true}
      />
      <ValidateMemoization
        in

puts={[b]}
        output={[hasB]}
        onlyCheckCompiled={true}
      />
    </>
  );
}

const v1 = {value: 1};
const v2 = {value: 2};
const v3 = {value: 3};
export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{a:


but hard to compute by brute-forcing
function MyComponent() {
  // 40 conditions
  if (c) {
  } else {
  }
  if (c) {
  } else {
  }
  if (c) {
  } else {
  }
  if (c) {
  } else {
  }
  if (c) {
  } else {
  }
  if (c) {
  } else {
  }
  if (c) {
  } else {
  }
  if (c) {
  } else {
  }
  if (c) {
  } else {
  }
  if (c) {
  } else {
  }
  if (c) {
  } else {
  }
  if (c) {
  } else {
  }
  if (c) {
  } else {
  }
  if (c) {
  } else {
  }
  if (c) {
  } else {
  }
  if (c) {
  } else {
  }
  if (c) {
  }


 neither the conditions before or after the hook affect the hook call
// Failed prior to implementing BigInt because pathsFromStartToEnd and allPathsFromStartToEnd were too big and had rounding errors
const useSomeHook = () => {};

const SomeName = () => {
  const filler = FILLER ?? FILLER ?? FILLER;
  const filler2 = FILLER ?? FILLER ?? FILLER;
  const filler3 = FILLER ?? FILLER ?? FILLER;
  const filler4 = FILLER ?? FILLER ?? FILLER;
  const filler5 = FILLER ?? FILLER ?? FILLER;
  const filler6 = FILLER ?

ILLER ? FILLER : FILLER}
      {FILLER ? FILLER : FILLER}
      {FILLER ? FILLER : FILLER}
      {FILLER ? FILLER : FILLER}
      {FILLER ? FILLER : FILLER}
      {FILLER ? FILLER : FILLER}
      {FILLER ? FILLER : FILLER}
      {FILLER ? FILLER : FILLER}

? FILLER ?? FILLER;
  const filler7 = FILLER ?? FILLER ?? FILLER;
  const filler8 = FILLER ?? FILLER ?? FILLER;

  useSomeHook();

  if (anyConditionCanEvenBeFalse) {
    return null;
  }

  return (
    <React.Fragment>
      {F


@validateExhaustiveMemoizationDependencies
import {useMemo} from 'react';
import {Stringify} from 'shared-runtime';

function Component({x, y, z}) {
  const a = useMemo(() => {
    return x?.y.z?.a;
    // error: too precise
  }, [x?.y.z?.a.b]);
  const b = useMemo(() => {
    return x.y.z?.a;
    // ok, not our job to type check nullability
  }, [x.y.z.a]);
  const c = useMemo(() => {
    return x?.y.z.a?.b;
    // error: too precise
  }, [x?.y.z.a?.b.z]);
  const d = useMemo(() => {
    return x?.y?.[(con

.z, z?.y?.a, UNUSED_GLOBAL]);
  const ref1 = useRef(null);
  const ref2 = useRef(null);
  const ref = z ? ref1 : ref2;
  const cb = useMemo(() => {
    return () => {
      return ref.current;
    };
    // error: ref is a stable type but reactive
  }, [])

sole.log(y), z?.b)];
    // ok
  }, [x?.y, y, z?.b]);
  const e = useMemo(() => {
    const e = [];
    e.push(x);
    return e;
    // ok
  }, [x]);
  const f = useMemo(() => {
    return [];
    // error: unnecessary
  }, [x, y


ExhaustiveMemoizationDependencies @validateExhaustiveEffectDependencies:"all"
import {
  useCallback,
  useTransition,
  useState,
  useOptimistic,
  useActionState,
  useRef,
  useReducer,
  useEffect,
} from 'react';

function useFoo() {
  const [s, setState] = useState();
  const ref = useRef(null);
  const [t, startTransition] = useTransition();
  const [u, addOptimistic] = useOptimistic();
  const [v, dispatch] = useReducer(() => {}, null);
  const [isPending, dispatchAction] = useActionState(() => {},

 stable values
    // to check that they're allowed
    dispatch,
    startTransition,
    addOptimistic,
    setState,
    dispatchAction,
    ref,
  ]);

  return useCallback(() => {
    dispatch();
    startTransition(() => {});
    addOptimistic();

 null);

  useEffect(() => {
    dispatch();
    startTransition(() => {});
    addOptimistic();
    setState(null);
    dispatchAction();
    ref.current = true;
  }, [
    // intentionally adding unnecessary deps on nonreactive


ExhaustiveMemoizationDependencies
import {useCallback, useMemo} from 'react';
import {makeObject_Primitives, Stringify} from 'shared-runtime';

function useHook1(x) {
  return useMemo(() => {
    return x?.y.z?.a;
  }, [x?.y.z?.a]);
}
function useHook2(x) {
  useMemo(() => {
    return x.y.z?.a;
  }, [x.y.z?.a]);
}
function useHook3(x) {
  return useMemo(() => {
    return x?.y.z.a?.b;
  }, [x?.y.z.a?.b]);
}
function useHook4(x, y, z) {
  return useMemo(() => {
    return x?.y?.[(console.log(y), z?.b)];
  }

useHook6(x) {
  return useMemo(() => {
    const f = [];
    f.push(x.y.z);
    f.push(x.y);
    f.push(x);
    return f;
  }, [x]);
}

function useHook7(x) {
  const [state, setState] = useState(true);
  const f = () => {
    setState(x => !x);
  };
  ret

, [x?.y, y, z?.b]);
}
function useHook5(x) {
  return useMemo(() => {
    const e = [];
    const local = makeObject_Primitives(x);
    const fn = () => {
      e.push(local);
    };
    fn();
    return e;
  }, [x]);
}
function


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

/**
 * Repro for bug with `mutableOnlyIfOperandsAreMutable` flag
 * Found differences in evaluator results
  * Non-forget (expected):
  * (kind: ok)
  *
{"children":[{"value":"foo","wat0":"joe"},{"value":5,"wat0":"joe"}]}

  *
{"children":[{"value":"foo","wat0":"joe"},{"value":6,"wat0":"joe"}]}

  *
{"children":[{"value":"foo","wat0":"joe"},{"value":6,"wat0":"joe"}]}

  * Forget:
  * (kind: ok)
  *
{"childr

"value":6,"wat0":"joe"}]}</div>

 */
function Component({value}) {
  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];
  useIdentity(null);
  const derived = arr.filter(mutateAndReturn);
  return (
    <Stringify>
      {derived.at(0)}
      {derived.


.todo-multiple-fbt-plural, but note that we must
 * count fbt plurals across both <fbt:plural /> namespaced jsx tags
 * and fbt.plural(...) call expressions.
 *
 * Evaluator error:
 *   Found differences in evaluator results
 *   Non-forget (expected):
 *   (kind: ok)
1 apple and 2 bananas

 *   Forget:
 *   (kind: ok)
1 apples and 2 bananas

 */
function useFoo({apples, bananas}) {
  return (

      <fbt desc="Test Description">
        {fbt.param('number of apples', apples)}

and
        {'  '}
        <fbt:plural name={'number of bananas'} count={bananas} showCount="yes">
          banana
        </fbt:plural>
      </fbt>
    </div>
  );
}

export const FIXTURE_ENTRYPOINT = {
  fn: useFoo,
  params: [{apples: 1, bananas: 2}],

       {'  '}
        {fbt.plural('apple', apples)}


* Note that the fbt transform looks for callsites with a `fbt`-named callee.
 * This is incompatible with react-compiler as we rename local variables in
 * HIRBuilder + RenameVariables.
 *
 * See evaluator error:
 *   Found differences in evaluator results
 *   Non-forget (expected):
 *   (kind: ok)
Hello, Sathya!Goodbye, Sathya!

 *   Forget:
 *   (kind: exception) fbt$0.param is not a function
 */

function Foo(props) {
  const getText1 = fbt =>
    fbt(
      `Hello, ${fbt.param('(key) name', i

ng'
    );

  const getText2 = fbt =>
    fbt(
      `Goodbye, ${fbt.param('(key) name', identity(props.name))}!`,
      '(description) Greeting2'
    );

  return (
    <div>
      {getText1(fbt)}
      {getText2(fbt)}
    </div>
  );
}

export const FIXT


**
 * Forget + fbt inconsistency. Evaluator errors with the following
 *   Found differences in evaluator results
 *   Non-forget (expected):
 *   (kind: ok) 1 rewrite to Rust · 2 months traveling
 *   Forget:
 *   (kind: ok) 1 rewrites to Rust · 2 months traveling
 *
 * The root issue here is that fbt:plural/enum/pronoun read `.start` and `.end` from
 * babel nodes to slice into source strings for some complex dedupe logic
 * (see [_getStringVariationCombinations](https://github.com/facebook/fbt/blob/main/

/FbtUtil.js#L666-L673)
 * simply returns the whole source code string. As a result, all fbt nodes dedupe together
 * and _getStringVariationCombinations ends up early exiting (before adding valid candidate values).
 *
 *
 *
 * For fbt:plural tags specifica

packages/babel-plugin-fbt/src/JSFbtBuilder.js#L297))
 *
 *
 * Since Forget does not add `.start` and `.end` for babel nodes it synthesizes,
 * [getRawSource](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src


ort fbt from 'fbt';
import {Stringify, identity} from 'shared-runtime';

/**
 * MemoizeFbtAndMacroOperands needs to account for nested fbt calls.
 * Expected fixture `fbt-param-call-arguments` to succeed but it failed with error:
 *   /fbt-param-call-arguments.ts: Line 19 Column 11: fbt: unsupported babel node: Identifier
 *   ---
 *   t3
 *   ---
 */
function Component({firstname, lastname}) {
  'use memo';
  return (
    <div>
      {fbt(
        [
          'Name: ',
          fbt.param('firstname', <Str

e={lastname} />),
                'Inner fbt value'
              )
            )
          ),
        ],
        'Name'
      )}
    </div>
  );
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{firstname: 'first', lastname: 'last'}],

ingify key={0} name={firstname} />),
          ', ',
          fbt.param(
            'lastname',
            identity(
              fbt(
                '(inner)' +
                  fbt.param('lastname', <Stringify key={1} nam


import fbt from 'fbt';
import {identity} from 'shared-runtime';

/**
 * MemoizeFbtAndMacroOperands needs to account for nested fbt calls.
 * Expected fixture `fbt-param-call-arguments` to succeed but it failed with error:
 *   /fbt-param-call-arguments.ts: Line 19 Column 11: fbt: unsupported babel node: Identifier
 *   ---
 *   t3
 *   ---
 */
function Component({firstname, lastname}) {
  'use memo';
  return (
    <div>
      {fbt(
        [
          'Name: ',
          fbt.param('firstname', identity(fir

  )
            )
          ),
        ],
        'Name'
      )}
    </div>
  );
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{firstname: 'first', lastname: 'last'}],
  sequentialRenders: [{firstname: 'first', lastname: 'last'}],
};

stname)),
          ', ',
          fbt.param(
            'lastname',
            identity(
              fbt(
                '(inner)' + fbt.param('lastname', identity(lastname)),
                'Inner fbt value'


 {throwErrorWithMessage, ValidateMemoization} from 'shared-runtime';

/**
 * Context variables are local variables that (1) have at least one reassignment
 * and (2) are captured into a function expression. These have a known mutable
 * range: from first declaration / assignment to the last direct or aliased,
 * mutable reference.
 *
 * This fixture validates that forget can take granular dependencies on context
 * variables when the reference to a context var happens *after* the end of its
 * mutable range

 specify input to avoid adding a `PropertyLoad` from contextVar,
   * which might affect hoistable-objects analysis.
   */
  return (
    <ValidateMemoization
      inputs={[cond ? a : undefined]}
      output={cb}
      onlyCheckCompiled={true}
    />
  )

.
 */
function Component({cond, a}) {
  let contextVar;
  if (cond) {
    contextVar = {val: a};
  } else {
    contextVar = {};
    throwErrorWithMessage('');
  }
  const cb = {cb: () => contextVar.val * 4};

  /**
   * manually


ngify, useIdentity} from 'shared-runtime';

type HasA = {kind: 'hasA'; a: {value: number}};
type HasC = {kind: 'hasC'; c: {value: number}};
function Foo({cond}: {cond: boolean}) {
  let x: HasA | HasC = shallowCopy({kind: 'hasA', a: {value: 2}});
  /**
   * This read of x.a.value is outside of x's identifier mutable
   * range + scope range. We mark this ssa instance (x_@0) as having
   * a non-null object property `x.a`.
   */
  Math.max(x.a.value, 2);
  if (cond) {
    x = shallowCopy({kind: 'hasC', c: {v

(x_@0, x_@1)) is a different ssa instance,
   * we cannot safely hoist a read of `x.a.value`
   */
  return <Stringify val={!cond && [(x as HasA).a.value + 2]} />;
}
export const FIXTURE_ENTRYPOINT = {
  fn: Foo,
  params: [{cond: false}],
  sequentialRend

alue: 3}});
  }

  /**
   * Since this x (x_@2 = phi


encies 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);
//    }
//    mutate2(y, props.a.b);
//  }

import {CONST_TR

eJoinCondDepsInUncondScopes(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 = {
  fn: useJoinCondDepsInUncondScopes,
  params: [{a:

UE, setProperty} from 'shared-runtime';

function us


 unconditional dependency `props.a` is the subpath of a conditional
// dependency `props.a.b`, we can safely overestimate and only track `props.a`
// as a dependency

import {identity} from 'shared-runtime';

// ordering of accesses should not matter
function useConditionalSuperpath1({props, cond}) {
  const x = {};
  x.a = props.a;
  if (identity(cond)) {
    x.b = props.a.b;
  }
  return x;
}

export const FIXTURE_ENTRYPOINT = {
  fn: useConditionalSuperpath1,
  params: [{props: {a: null}, cond: false}],

nders: [
    {props: {a: null}, cond: false},
    {props: {a: {}}, cond: true},
    {props: {a: {b: 3}}, cond: true},
    {props: {}, cond: false},
    // test that we preserve nullthrows
    {props: {a: {b: undefined}}, cond: true},
    {props: {a: undefi


 unconditional dependency `props.a` is the subpath of a conditional
// dependency `props.a.b`, we can safely overestimate and only track `props.a`
// as a dependency

import {identity} from 'shared-runtime';

// ordering of accesses should not matter
function useConditionalSuperpath2({props, cond}) {
  const x = {};
  if (identity(cond)) {
    x.b = props.a.b;
  }
  x.a = props.a;
  return x;
}

export const FIXTURE_ENTRYPOINT = {
  fn: useConditionalSuperpath2,
  params: [{props: {a: null}, cond: false}],


pertyByKey,
} from 'shared-runtime';

/**
 * This fixture is similar to `bug-aliased-capture-aliased-mutate` and
 * `nonmutating-capture-in-unsplittable-memo-block`, but with a focus on
 * dependency extraction.
 *
 * NOTE: this fixture is currently valid, but will break with optimizations:
 * - Scope and mutable-range based reordering may move the array creation
 *     *after* the `mutate(aliasedObj)` call. This is invalid if mutate
 *     reassigns inner properties.
 * - RecycleInto or other deeper-equali

ptured into the array.
 *
 * Before scope block creation, HIR looks like this:
 *  //
 *  // $1 is unscoped as obj's mutable range will be
 *  // extended in a later pass
 *  //
 *  $1    = LoadLocal obj@0[0:12]
 *  $2    = PropertyLoad $1.id
 *  //
 *  //

ty optimizations may produce invalid
 *     output -- it may compare the array's contents / dependencies too early.
 * - Runtime validation for immutable values will break if `mutate` does
 *     interior mutation of the value ca


// @enableNewMutationAliasingModel
import {Stringify} from 'shared-runtime';

/**
 * Forked from array-map-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

{getArrMap2}
      shouldInvokeFns={true}
    />
  );
}

export const FIXTURE_ENTRYPOINT = {
  fn: useFoo,
  params: [{arr1: [], arr2: []}],
  sequentialRenders: [
    {arr1: [], arr2: []},
    {arr1: [], arr2: null},
    {arr1: [{value: 1}, {value: 2}], a

=> arr1[0].value + e.value;
  const getArrMap1 = () => arr1.map(cb1);
  const cb2 = e => arr2[0].value + e.value;
  const getArrMap2 = () => arr1.map(cb2);
  return (
    <Stringify
      getArrMap1={getArrMap1}
      getArrMap2=


wMutationAliasingModel
import {arrayPush, Stringify} from 'shared-runtime';

function Component({prop1, prop2}) {
  'use memo';

  let x = [{value: prop1}];
  let z;
  while (x.length < 2) {
    // there's a phi here for x (value before the loop and the reassignment later)

    // this mutation occurs before the reassigned value
    arrayPush(x, {value: prop2});

    if (x[0].value === prop1) {
      x = [{value: prop2}];
      const y = x;
      z = y[0];
    }
  }
  z.other = true;
  return <Stringify z={

rt const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{prop1: 0, prop2: 'a'}],
  sequentialRenders: [
    {prop1: 0, prop2: 'a'},
    {prop1: 1, prop2: 'a'},
    {prop1: 1, prop2: 'b'},
    {prop1: 0, prop2: 'b'},
    {prop1: 0, prop2: 'a'},
  ],
};


@enableNewMutationAliasingModel
function Component() {
  let local;

  const reassignLocal = newValue => {
    local = newValue;
  };

  const onClick = newValue => {
    reassignLocal('hello');

    if (local === newValue) {
      // Without React Compiler, `reassignLocal` is freshly created
      // on each render, capturing a binding to the latest `local`,
      // such that invoking reassignLocal will reassign the same
      // binding that we are observing in the if condition, and
      // we reach thi

 `reassignLocal` will reassign the wrong
      // version of `local`, and not update the binding we are checking
      // in the if condition.
      //
      // To protect against this, we disallow reassigning locals from
      // functions that escape

s branch
      console.log('`local` was updated!');
    } else {
      // With React Compiler enabled, `reassignLocal` is only created
      // once, capturing a binding to `local` in that render pass.
      // Therefore, calling


nt Component(
  onAsyncSubmit?: (() => void) => void,
  onClose: (isConfirmed: boolean) => void
) {
  // When running inferReactiveScopeVariables,
  // onAsyncSubmit and onClose update to share
  // a mutableRange instance.
  const onSubmit = useCallback(() => {
    if (onAsyncSubmit) {
      onAsyncSubmit(() => {
        onClose(true);
      });
      return;
    }
  }, [onAsyncSubmit, onClose]);
  // When running inferReactiveScopeVariables here,
  // first the existing range gets updated (affecting
  //

 different mutable range instance, which is the
  // one reset after AnalyzeFunctions.
  // The fix is to fully reset mutable ranges *instances*
  // after AnalyzeFunctions visit a function expression
  return <Dialog onSubmit={onSubmit} onClose={() => onC

onAsyncSubmit) and then onClose gets assigned a
  //


@enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import {useMemo} from 'react';
import {
  mutate,
  typedCapture,
  typedCreateFrom,
  typedMutate,
  ValidateMemoization,
} from 'shared-runtime';

function Component({a, b, c}: {a: number; b: number; c: number}) {
  const x = useMemo(() => [{value: a}], [a, b, c]);
  if (b === 0) {
    // This object should only depend on c, it cannot be affected by the later mutation
    x.push({value: c});
  } else {

ion inputs={[a, b, c]} output={x[0]} />;
    </>
  );
}

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

// This mutation shouldn't affect the object in the consequent
    mutate(x);
  }

  return (
    <>
      <ValidateMemoization inputs={[a, b, c]} output={x} />;
      {/* TODO: should only depend on c */}
      <ValidateMemoizat


import {useMemo} from 'react';
import {
  identity,
  makeObject_Primitives,
  typedIdentity,
  useIdentity,
  ValidateMemoization,
} from 'shared-runtime';

function Component({a, b}) {
  // create a mutable value with input `a`
  const x = useMemo(() => makeObject_Primitives(a), [a]);

  // freeze the value
  useIdentity(x);

  // known to pass-through via aliasing signature
  const x2 = typedIdentity(x);

  // Unknown function so we assume it conditionally mutates,
  // but x2 is frozen so this downgrad

ency
  identity(x2, b);

  return <ValidateMemoization inputs={[a]} output={x} />;
}

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: 0, b:

es to a read.
  // x should *not* take b as a depend


rops) {
  const a_DEBUG = [];
  a_DEBUG.push(props.a);
  if (props.b) {
    return null;
  }
  a_DEBUG.push(props.d);
  return a_DEBUG;
}

/**
 * props.b *does* influence `a`
 */
function ComponentB(props) {
  const a = [];
  a.push(props.a);
  if (props.b) {
    a.push(props.c);
  }
  a.push(props.d);
  return a;
}

/**
 * props.b *does* influence `a`, but only in a way that is never observable
 */
function ComponentC(props) {
  const a = [];
  a.push(props.a);
  if (props.b) {
    a.push(props.c);
    ret

 * props.b *does* influence `a`
 */
function ComponentD(props) {
  const a = [];
  a.push(props.a);
  if (props.b) {
    a.push(props.c);
    return a;
  }
  a.push(props.d);
  return a;
}

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

urn null;
  }
  a.push(props.d);
  return a;
}

/**


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

const FooContext = React.createContext(null);
function Component(props) {
  return (
    <FooContext.Provider value={props.value}>
      <Inner cond={props.cond} />
    </FooContext.Provider>
  );
}

function Inner(props) {
  let input = null;
  if (props.cond) {
    input = use(FooContext);
  }
  const output = useMemo(() => [input], [input]);
  return <ValidateMemoization inputs={[input]} output={output} />;
}

export

alse, value: null},
    {cond: false, value: 42},

    // change cond false->true
    {cond: true, value: 42},

    // change cond true->false, change unobserved value, change cond false->true
    {cond: false, value: 42},
    {cond: false, value: null},

const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{cond: true, value: 42}],
  sequentialRenders: [
    // change cond true->false
    {cond: true, value: 42},
    {cond: false, value: 42},

    // change value
    {cond: f


ableAllowSetStateFromRefsInEffects @loggerTestOnly @compilationMode:"infer" @outputMode:"lint"
import {useState, useRef, useEffect} from 'react';

function Component({x, y}) {
  const previousXRef = useRef(null);
  const previousYRef = useRef(null);

  const [data, setData] = useState(null);

  useEffect(() => {
    const previousX = previousXRef.current;
    previousXRef.current = x;
    const previousY = previousYRef.current;
    previousYRef.current = y;
    if (!areEqual(x, previousX) || !areEqual(y, pr

etData(data);
    }
  }, [x, y]);

  return data;
}

function areEqual(a, b) {
  return a === b;
}

function load({x, y}) {
  return x * y;
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{x: 0, y: 0}],
  sequentialRenders: [
    {x: 0,

eviousY)) {
      const data = load({x, y});
      s


 {useEffect} from 'react';
import {useIdentity} from 'shared-runtime';

function Component() {
  let local;

  const reassignLocal = newValue => {
    local = newValue;
  };

  const callback = newValue => {
    reassignLocal('hello');

    if (local === newValue) {
      // Without React Compiler, `reassignLocal` is freshly created
      // on each render, capturing a binding to the latest `local`,
      // such that invoking reassignLocal will reassign the same
      // binding that we are observing in th

 render pass.
      // Therefore, calling `reassignLocal` will reassign the wrong
      // version of `local`, and not update the binding we are checking
      // in the if condition.
      //
      // To protect against this, we disallow reassigning local

e if condition, and
      // we reach this branch
      console.log('`local` was updated!');
    } else {
      // With React Compiler enabled, `reassignLocal` is only created
      // once, capturing a binding to `local` in that


 useRef();

  function updateStyles() {
    const foo = fooRef.current;
    // The access of `barRef` here before its declaration causes it be hoisted...
    if (barRef.current == null || foo == null) {
      return;
    }
    foo.style.height = '100px';
  }

  // ...which previously meant that we didn't infer a type...
  const barRef = useRef(null);

  const resizeRef = useResizeObserver(
    rect => {
      const {width} = rect;
      // ...which meant that we failed to ignore the mutation here...
      b

 to fail with "can't freeze a mutable function"
  );

  useLayoutEffect(() => {
    const observer = new ResizeObserver(_ => {
      updateStyles();
    });

    return () => {
      observer.disconnect();
    };
  }, []);

  return <div ref={resizeRef} />

arRef.current = width;
    } // ...which caused this


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

// derived from https://github.com/facebook/react/issues/32261
function Component({items}) {
  const record = useMemo(
    () =>
      Object.fromEntries(
        items.map(item => [item.id, ref => <Stringify ref={ref} {...item} />])
      ),
    [items]
  );

  // Without a declaration for Object.entries(), this would be assumed to mutate
  // `record`, meaning existing memoization couldn't be preserv

).map(([id, render]) => (
        <Stringify key={id} render={render} />
      ))}
    </div>
  );
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [
    {
      items: [
        {id: '0', name: 'Hello'},
        {id: '1', name: 'World!'},

ed
  return (
    <div>
      {Object.entries(record


1?: V3}>): V2b.V2a {
  const v4 = v5(V6.v7({v8: V9.va}));
  const vb = (
    <ComponentC cd="TxqUy" ce="oh`]uc" cf="Bdbo" c10={!V9.va && v11.v12}>
      gmhubcw
      {v1 === V3.V13 ? (
        <c14 c15="L^]w\\T\\qrGmqrlQyrvBgf\\inuRdkEqwVPwixiriYGSZmKJf]E]RdT{N[WyVPiEJIbdFzvDohJV[BV`H[[K^xoy[HOGKDqVzUJ^h">
          iawyneijcgamsfgrrjyvhjrrqvzexxwenxqoknnilmfloafyvnvkqbssqnxnexqvtcpvjysaiovjxyqrorqskfph
        </c14>
      ) : v16.v17('pyorztRC]EJzVuP^e') ? (
        <c14 c15="CRinMqvmOknWRAKERI]RBzB_LXGK

mmjhfserfuqyluxcewpyjihektogc
        </c14>
      ) : (
        <c14 c15="H\\\\GAcTc\\lfGMW[yHriCpvW`w]niSIKj\\kdgFI">
          yejarlvudihqdrdgpvahovggdnmgnueedxpbwbkdvvkdhqwrtoiual
        </c14>
      )}
      hflmn
    </ComponentC>
  );
  return vb;

Qe{SUpoN[\\gL[`bLMOhvFqDVVMNOdY">
          goprinbj


 expressions should not be
 * typed with `freeze` effects.
 */
function Foo({a, b}) {
  'use memo';
  const obj = {};
  const updaterFactory = () => {
    /**
     * 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 would be incorrect as it would mean
     * inferring that calls to updaterFactory()() do not mutate its captured
     * context.
     */
    retur

j.a = a;
    };
  };

  const updater = updaterFactory();
  updater(b);
  return <Stringify cb={obj} shouldInvokeFns={true} />;
}

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

n newValue => {
      obj.value = newValue;
      ob


*
 * Repro for https://github.com/facebook/react/issues/35122
 *
 * InferReactiveScopeVariables was excluding primitive operands
 * when considering operands for merging. We previously did not
 * infer types for context variables (StoreContext etc), but later
 * started inferring types in cases of `const` context variables,
 * since the type cannot change.
 *
 * In this example, this meant that we skipped the `isExpired`
 * operand of the onClick function expression when considering
 * scopes to merge.
 */

State(5);

  const onClick = () => {
    // Reference to isExpired prior to declaration
    console.log('isExpired', isExpired);
  };

  const isExpired = expire === 0;

  return
{expire}
;
}

export const FIXTURE_ENTRYPOINT = {

function Test1() {
  const [expire, setExpire] = use


aticText1, Stringify, Text} from 'shared-runtime';

function Component(props) {
  const {buttons} = props;
  const [primaryButton, ...nonPrimaryButtons] = buttons;

  const renderedNonPrimaryButtons = nonPrimaryButtons.map((buttonProps, i) => (
    <Stringify
      {...buttonProps}
      key={`button-${i}`}
      style={
        i % 2 === 0 ? styles.leftSecondaryButton : styles.rightSecondaryButton
      }
    />
  ));

  return <StaticText1>{renderedNonPrimaryButtons}</StaticText1>;
}

const styles = {
  l

tton: {left: true},
  rightSecondaryButton: {right: true},
};

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [
    {
      buttons: [
        {},
        {type: 'submit', children: ['Submit!']},
        {type: 'button', children: ['Reset']


t(props) {
  const data = useFreeze(); // assume this returns {items: Array<{...}>}
  // In this call `data` and `data.items` have a read effect *and* the lambda itself
  // is readonly (it doesn't capture ony mutable references). Further, we ca
  // theoretically determine that the lambda doesn't need to be memoized, since
  // data.items is an Array and Array.prototype.map does not capture its input (callback)
  // in the return value.
  // An observation is that even without knowing the exact type of `da

vascript object, then we can infer that any `.map()`
  // calls *must* be Array.prototype.map (or else they are a runtime error), since no
  // other builtin has a .map() function.
  const items = data.items.map(item => <Item item={item} />);
  return <div

ta`, if we know
  // that it is a plain, readonly ja


ion Component({cond, obj, items}) {
  try {
    // items.length is accessed WITHIN the && expression
    const result = cond && obj?.value && items.length;
    return
{String(result)}
;
  } catch {
    return
error
;
  }
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{cond: true, obj: {value: 'hello'}, items: [1, 2]}],
  sequentialRenders: [
    {cond: true, obj: {value: 'hello'}, items: [1, 2]},
    {cond: true, obj: {value: 'hello'}, items: [1, 2]},
    {cond: true,

: false, obj: {value: 'hello'}, items: [1]},
    {cond: true, obj: null, items: [1]},
    {cond: true, obj: {value: 'test'}, items: null}, // errors because items.length throws WITHIN the && chain
    {cond: null, obj: {value: 'test'}, items: [1]},
  ],
};

 obj: {value: 'world'}, items: [1, 2, 3]},
    {cond


Component({a, b, fallback}) {
  try {
    // fallback.value is accessed WITHIN the ?? chain
    const result = a ?? b ?? fallback.value;
    return {result};
  } catch {
    return error;
  }
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{a: 'first', b: 'second', fallback: {value: 'default'}}],
  sequentialRenders: [
    {a: 'first', b: 'second', fallback: {value: 'default'}},
    {a: 'first', b: 'second', fallback: {value: 'default'}},
    {a: null, b: 'secon

null, fallback: {value: 'fallback'}},
    {a: undefined, b: undefined, fallback: {value: 'fallback'}},
    {a: 0, b: 'not zero', fallback: {value: 'default'}},
    {a: null, b: null, fallback: null}, // errors because fallback.value throws WITHIN the ?? ch


WITHIN the optional call expression as an argument
    // When obj is non-null but arg is null, arg.value throws inside the optional chain
    const result = obj?.method?.(arg.value);
    return {result ?? 'no result'};
  } catch {
    return error;
  }
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{obj: {method: x => 'called:' + x}, arg: {value: 1}}],
  sequentialRenders: [
    {obj: {method: x => 'called:' + x}, arg: {value: 1}},
    {obj: {method: x => 'call

 'different:' + x}, arg: {value: 2}},
    {obj: {method: null}, arg: {value: 3}},
    {obj: {notMethod: true}, arg: {value: 4}},
    {obj: null, arg: {value: 5}}, // obj is null, short-circuits so arg.value is NOT evaluated
    {obj: {method: x => 'test:'


rt * as SharedRuntime from 'shared-runtime';

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

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

ion inputs={[a, b]} output={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,

={items[1]} />
      <SharedRuntime.ValidateMemoizat


:false @validateExhaustiveMemoizationDependencies:false
import {useMemo} from 'react';
import {identity, makeObject_Primitives, mutate, useHook} from 'shared-runtime';

function Component(props) {
  // With the feature disabled these variables are inferred as being mutated inside the useMemo block
  const free = makeObject_Primitives();
  const free2 = makeObject_Primitives();
  const part = free2.part;

  // This causes their range to extend to include this hook call, and in turn for the memoization to be

    const x = makeObject_Primitives();
    x.value = props.value;
    mutate(x, free, part);
    return x;
  }, [props.value]);

  identity(free);
  identity(part);
  return object;
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{value

pruned
  useHook();
  const object = useMemo(() => {


NoSetStateInEffects @enableAllowSetStateFromRefsInEffects @loggerTestOnly @compilationMode:"infer"
import {useState, useRef, useEffect, useEffectEvent} from 'react';

function Component({x, y}) {
  const previousXRef = useRef(null);
  const previousYRef = useRef(null);

  const [data, setData] = useState(null);

  const effectEvent = useEffectEvent(() => {
    const data = load({x, y});
    setData(data);
  });

  useEffect(() => {
    const previousX = previousXRef.current;
    previousXRef.current = x;

   const previousX = previousXRef.current;
    previousXRef.current = xx;
    const previousY = previousYRef.current;
    previousYRef.current = yy;
    if (!areEqual(xx, previousX) || !areEqual(yy, previousY)) {
      const data = load({x: xx, y: yy});

  const previousY = previousYRef.current;
    previousYRef.current = y;
    if (!areEqual(x, previousX) || !areEqual(y, previousY)) {
      effectEvent();
    }
  }, [x, y]);

  const effectEvent2 = useEffectEvent((xx, yy) => {