function act(cb) {
	if (++actDepth > 1) {
		// If calls to `act` are nested, a flush happens only when the
		// outermost call returns. In the inner call, we just execute the
		// callback and return since the infrastructure for flushing has already
		// been set up.
		//
		// If an exception occurs, the outermost `act` will handle cleanup.
		try {
			const result = cb();
			if (isThenable(result)) {
				return result.then(
					() => {
						--actDepth;
					},
					e => {
						--actDepth;
						throw e;
					}
				);
			}
		} catch (e) {
			--actDepth;
			throw e;
		}
		--actDepth;
		return Promise.resolve();
	}

	const previousRequestAnimationFrame = options.requestAnimationFrame;
	const rerender = setupRerender();

	/** @type {() => void} */
	let flushes = [], toFlush;

	// Override requestAnimationFrame so we can flush pending hooks.
	options.requestAnimationFrame = fc => flushes.push(fc);

	const finish = () => {
		try {
			rerender();
			while (flushes.length) {
				toFlush = flushes;
				flushes = [];

				toFlush.forEach(x => x());
				rerender();
			}
		} catch (e) {
			if (!err) {
				err = e;
			}
		} finally {
			teardown();
		}

		options.requestAnimationFrame = previousRequestAnimationFrame;
		--actDepth;
	};

	let err;
	let result;

	try {
		result = cb();
	} catch (e) {
		err = e;
	}

	if (isThenable(result)) {
		return result.then(finish, err => {
			finish();
			throw err;
		});
	}

	// nb. If the callback is synchronous, effects must be flushed before
	// `act` returns, so that the caller does not have to await the result,
	// even though React recommends this.
	finish();
	if (err) {
		throw err;
	}
	return Promise.resolve();
}
Run a test function, and flush all effects and rerenders after invoking it.

Returns a Promise which resolves "immediately" if the callback is
synchronous or when the callback's result resolves if it is asynchronous.

@param {() => void|Promise<void>} cb The function under test. This may be sync or async.
@return {Promise<void>}