diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalTriangle-test.js b/packages/react-reconciler/src/__tests__/ReactIncrementalTriangle-test.js
deleted file mode 100644
index b3f70d6e25da6..0000000000000
--- a/packages/react-reconciler/src/__tests__/ReactIncrementalTriangle-test.js
+++ /dev/null
@@ -1,592 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @emails react-core
- * @jest-environment node
- */
-
-'use strict';
-
-let React;
-let ReactNoop;
-let Scheduler;
-
-describe('ReactIncrementalTriangle', () => {
- beforeEach(() => {
- jest.resetModules();
-
- React = require('react');
- ReactNoop = require('react-noop-renderer');
- Scheduler = require('scheduler');
- });
-
- function span(prop) {
- return {type: 'span', children: [], prop, hidden: false};
- }
-
- const FLUSH = 'FLUSH';
- function flush(unitsOfWork = Infinity) {
- return {
- type: FLUSH,
- unitsOfWork,
- };
- }
-
- const FLUSH_ALL = 'FLUSH_ALL';
- function flushAll() {
- return {
- type: FLUSH_ALL,
- };
- }
-
- const STEP = 'STEP';
- function step(counter) {
- return {
- type: STEP,
- counter,
- };
- }
-
- const INTERRUPT = 'INTERRUPT';
- function interrupt(key) {
- return {
- type: INTERRUPT,
- };
- }
-
- const TOGGLE = 'TOGGLE';
- function toggle(childIndex) {
- return {
- type: TOGGLE,
- childIndex,
- };
- }
-
- const EXPIRE = 'EXPIRE';
- function expire(ms) {
- return {
- type: EXPIRE,
- ms,
- };
- }
-
- const STOP = 'STOP';
-
- function randomInteger(min, max) {
- min = Math.ceil(min);
- max = Math.floor(max);
- return Math.floor(Math.random() * (max - min)) + min;
- }
-
- function formatAction(action) {
- switch (action.type) {
- case FLUSH:
- return `flush(${action.unitsOfWork})`;
- case FLUSH_ALL:
- return 'flushAll()';
- case STEP:
- return `step(${action.counter})`;
- case INTERRUPT:
- return 'interrupt()';
- case TOGGLE:
- return `toggle(${action.childIndex})`;
- case EXPIRE:
- return `expire(${action.ms})`;
- default:
- throw new Error('Switch statement should be exhaustive');
- }
- }
-
- function formatActions(actions) {
- let result = 'simulate(';
- for (let i = 0; i < actions.length; i++) {
- const action = actions[i];
- result += formatAction(action);
- if (i !== actions.length - 1) {
- result += ', ';
- }
- }
- result += ')';
- return result;
- }
-
- const MAX_DEPTH = 3;
- const TOTAL_CHILDREN = Math.pow(3, MAX_DEPTH);
- let TOTAL_TRIANGLES = 0;
- for (let i = 0; i <= MAX_DEPTH; i++) {
- TOTAL_TRIANGLES += Math.pow(3, i);
- }
-
- function randomAction() {
- const weights = [
- [FLUSH, 1],
- [FLUSH_ALL, 1],
- [STEP, 1],
- [INTERRUPT, 1],
- [TOGGLE, 1],
- [EXPIRE, 1],
- ];
- let totalWeight = 0;
- for (let i = 0; i < weights.length; i++) {
- totalWeight += weights[i][1];
- }
-
- const randomNumber = Math.random() * totalWeight;
- let actionType;
- let remainingWeight = randomNumber;
- for (let i = 0; i < weights.length; i++) {
- const [option, weight] = weights[i];
- remainingWeight -= weight;
- if (remainingWeight <= 0) {
- actionType = option;
- break;
- }
- }
-
- switch (actionType) {
- case FLUSH:
- return flush(randomInteger(0, TOTAL_TRIANGLES * 1.5));
- case FLUSH_ALL:
- return flushAll();
- case STEP:
- return step(randomInteger(0, 10));
- case INTERRUPT:
- return interrupt();
- case TOGGLE:
- return toggle(randomInteger(0, TOTAL_TRIANGLES));
- case EXPIRE:
- return expire(randomInteger(0, 1500));
- default:
- throw new Error('Switch statement should be exhaustive');
- }
- }
-
- function randomActions(n) {
- const actions = [];
- for (let i = 0; i < n; i++) {
- actions.push(randomAction());
- }
- return actions;
- }
-
- function TriangleSimulator(rootID) {
- const CounterContext = React.createContext([]);
- const ActiveContext = React.createContext(0);
-
- let triangles = [];
- let leafTriangles = [];
- const yieldAfterEachRender = false;
- class Triangle extends React.Component {
- constructor(props) {
- super();
- this.state = {isActive: false};
- this.child = React.createRef(null);
- }
- activate() {
- this.setState({isActive: true});
- }
- deactivate() {
- this.setState({isActive: false});
- }
- shouldComponentUpdate(nextProps, nextState) {
- return (
- this.props.counter !== nextProps.counter ||
- this.props.activeDepth !== nextProps.activeDepth ||
- this.state.isActive !== nextState.isActive
- );
- }
- componentDidMount() {
- this.index = triangles.length;
- triangles.push(this);
- if (this.props.remainingDepth === 0) {
- this.leafIndex = leafTriangles.length;
- leafTriangles.push(this);
- }
- }
- componentDidUpdate() {
- if (this.child.current !== null) {
- const {prop: currentCounter} = JSON.parse(this.child.current.prop);
- if (this.props.counter !== currentCounter) {
- throw new Error('Incorrect props in lifecycle');
- }
- }
- }
- render() {
- if (yieldAfterEachRender) {
- Scheduler.log(this);
- }
- const {counter, remainingDepth} = this.props;
- return (
-
- {activeContext => (
-
- {counterContext => {
- const activeDepthProp = this.state.isActive
- ? this.props.activeDepth + 1
- : this.props.activeDepth;
- const activeDepthContext = this.state.isActive
- ? activeContext + 1
- : activeContext;
- if (remainingDepth === 0) {
- // Leaf
- const output = JSON.stringify({
- prop: counter,
- isActive: this.state.isActive,
- counterContext: counterContext,
- activeDepthProp,
- activeDepthContext,
- });
- return ;
- }
-
- return (
-
-
-
-
-
-
-
- );
- }}
-
- )}
-
- );
- }
- }
-
- let appInstance;
- class App extends React.Component {
- state = {counter: 0};
- interrupt() {
- // Triggers a restart from the top.
- this.forceUpdate();
- }
- setCounter(counter) {
- const currentCounter = this.state.counter;
- this.setState({counter});
- return currentCounter;
- }
- render() {
- appInstance = this;
- return (
-
- );
- }
- }
-
- let keyCounter = 0;
- function reset(nextStep = 0) {
- triangles = [];
- leafTriangles = [];
- // Remounts the whole tree by changing the key
- if (rootID) {
- ReactNoop.renderToRootWithID(
- ,
- rootID,
- );
- } else {
- ReactNoop.render();
- }
- Scheduler.unstable_flushAllWithoutAsserting();
- assertConsistentTree();
- return appInstance;
- }
-
- reset();
-
- function assertConsistentTree(activeTriangleIndices = new Set(), counter) {
- const childrenJSX = ReactNoop.getPendingChildrenAsJSX(rootID);
- const children = childrenJSX === null ? [] : childrenJSX.props.children;
-
- if (children.length !== TOTAL_CHILDREN) {
- throw new Error('Wrong number of children.');
- }
-
- let expectedCounter = counter;
-
- for (let i = 0; i < children.length; i++) {
- const child = children[i];
-
- const output = JSON.parse(child.props.prop);
- const prop = output.prop;
- const isActive = output.isActive;
- const counterContext = output.counterContext;
- const activeDepthProp = output.activeDepthProp;
- const activeDepthContext = output.activeDepthContext;
-
- // If an expected counter is not specified, use the value of the
- // first child.
- if (expectedCounter === undefined) {
- expectedCounter = prop;
- }
- const expectedIsActive = activeTriangleIndices.has(i);
-
- if (prop !== expectedCounter) {
- throw new Error(
- `Triangle ${i} is inconsistent: prop ${prop} instead of ` +
- expectedCounter,
- );
- }
-
- if (isActive !== expectedIsActive) {
- throw new Error(
- `Triangle ${i} is inconsistent: isActive ${isActive} instead of ` +
- expectedIsActive,
- );
- }
-
- if (counterContext !== prop) {
- throw new Error(
- `Triangle ${i} is inconsistent: prop ${prop} does not match ` +
- `counterContext ${counterContext}`,
- );
- }
-
- if (activeDepthContext !== activeDepthProp) {
- throw new Error(
- `Triangle ${i} is inconsistent: activeDepthProp ` +
- `${activeDepthProp} does not match activeDepthContext ` +
- activeDepthContext,
- );
- }
- }
- }
-
- function* simulateAndYield() {
- const app = reset();
- let expectedCounterAtEnd = app.state.counter;
-
- const activeIndices = new Set();
- const activeLeafIndices = new Set();
- let action;
- while (true) {
- action = yield;
- if (action === STOP) {
- break;
- }
- ReactNoop.flushSync(() => {
- switch (action.type) {
- case FLUSH:
- Scheduler.unstable_flushNumberOfYields(action.unitsOfWork);
- break;
- case FLUSH_ALL:
- Scheduler.unstable_flushAllWithoutAsserting();
- break;
- case STEP:
- ReactNoop.deferredUpdates(() => {
- app.setCounter(action.counter);
- expectedCounterAtEnd = action.counter;
- });
- break;
- case INTERRUPT:
- app.interrupt();
- break;
- case TOGGLE:
- const targetTriangle = triangles[action.childIndex];
- if (targetTriangle === undefined) {
- throw new Error('Target index is out of bounds');
- }
- const index = targetTriangle.index;
- const leafIndex = targetTriangle.leafIndex;
- if (activeIndices.has(index)) {
- activeIndices.delete(index);
- if (leafIndex !== undefined) {
- activeLeafIndices.delete(leafIndex);
- }
- targetTriangle.deactivate();
- } else {
- activeIndices.add(index);
- if (leafIndex !== undefined) {
- activeLeafIndices.add(leafIndex);
- }
- targetTriangle.activate();
- }
- break;
- case EXPIRE:
- ReactNoop.expire(action.ms);
- break;
- default:
- throw new Error('Switch statement should be exhaustive');
- }
- });
- assertConsistentTree(activeLeafIndices);
- }
- // Flush remaining work
- Scheduler.unstable_flushAllWithoutAsserting();
- ReactNoop.flushSync();
- assertConsistentTree(activeLeafIndices, expectedCounterAtEnd);
- }
-
- function simulate(...actions) {
- const gen = simulateAndYield();
- // Call this once to prepare the generator
- gen.next();
- // eslint-disable-next-line no-for-of-loops/no-for-of-loops
- for (const action of actions) {
- gen.next(action);
- }
- gen.next(STOP);
- }
-
- return {
- simulateAndYield,
- simulate,
- randomAction,
- randomActions,
- };
- }
-
- describe('single root', () => {
- // These tests are not deterministic because the inputs are randomized. It
- // runs a limited number of tests on every run. If it fails, it will output
- // the case that led to the failure. Add the failing case to the test above
- // to prevent future regressions.
- it('hard-coded tests', () => {
- const {simulate} = TriangleSimulator();
- simulate(step(1));
- simulate(toggle(0), step(1), toggle(0));
- simulate(step(1), toggle(0), flush(2), step(2), toggle(0));
- simulate(step(1), flush(3), toggle(0), step(0));
- simulate(step(1), flush(3), toggle(18), step(0));
- simulate(step(4), flush(52), expire(1476), flush(17), step(0));
- simulate(interrupt(), toggle(10), step(2), expire(990), flush(46));
- simulate(interrupt(), step(6), step(7), toggle(6), interrupt());
- simulate(interrupt(), toggle(31), toggle(31), toggle(13), step(1));
- });
-
- it('generative tests', () => {
- const {simulate} = TriangleSimulator();
-
- const limit = 1000;
-
- for (let i = 0; i < limit; i++) {
- const actions = randomActions(5);
- try {
- simulate(...actions);
- } catch (e) {
- console.error(
- `Triangle fuzz tester error! Copy and paste the following line into the test suite:
-${formatActions(actions)}
- `,
- );
- throw e;
- }
- }
- });
- });
-
- describe('multiple roots', () => {
- const rootIDs = ['a', 'b', 'c'];
-
- function randomActionsPerRoot() {
- function randomRootID() {
- const index = randomInteger(0, rootIDs.length);
- return rootIDs[index];
- }
-
- const actions = [];
- for (let i = 0; i < 10; i++) {
- const rootID = randomRootID();
- const action = randomAction();
- actions.push([rootID, action]);
- }
- return actions;
- }
-
- function formatActionsPerRoot(actions) {
- let result = 'simulateMultipleRoots(';
- for (let i = 0; i < actions.length; i++) {
- const [rootID, action] = actions[i];
- result += `['${rootID}', ${formatAction(action)}]`;
- if (i !== actions.length - 1) {
- result += ', ';
- }
- }
- result += ')';
- return result;
- }
-
- function simulateMultipleRoots(...actions) {
- const roots = new Map();
- // eslint-disable-next-line no-for-of-loops/no-for-of-loops
- for (const rootID of rootIDs) {
- const simulator = TriangleSimulator(rootID);
- const generator = simulator.simulateAndYield();
- // Call this once to prepare the generator
- generator.next();
- roots.set(rootID, generator);
- }
-
- actions.forEach(([rootID, action]) => {
- const generator = roots.get(rootID);
- generator.next(action);
- });
- roots.forEach(generator => {
- generator.next(STOP);
- });
- }
-
- it('hard-coded tests', () => {
- simulateMultipleRoots(
- ['b', interrupt()],
- ['a', toggle(22)],
- ['c', step(4)],
- ['a', expire(10)],
- ['a', interrupt()],
- ['c', step(2)],
- ['b', interrupt()],
- );
-
- simulateMultipleRoots(
- ['c', toggle(0)],
- ['c', step(1)],
- ['b', flush(7)],
- ['c', toggle(0)],
- );
-
- simulateMultipleRoots(
- ['c', step(1)],
- ['c', expire(5000)],
- ['b', toggle(1)],
- );
- });
-
- it('generative tests', () => {
- const limit = 100;
- for (let i = 0; i < limit; i++) {
- const actions = randomActionsPerRoot();
- try {
- simulateMultipleRoots(...actions);
- } catch (e) {
- console.error(
- `Triangle fuzz tester error! Copy and paste the following line into the test suite:
-${formatActionsPerRoot(actions)}
- `,
- );
- throw e;
- }
- }
- });
- });
-});