mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Merge cc03226eab into sapling-pr-archive-mofeiZ
This commit is contained in:
@@ -36,8 +36,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: compiler-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: compiler-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: npx playwright install --with-deps chromium
|
||||
- run: CI=true yarn test
|
||||
|
||||
@@ -46,8 +46,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: compiler-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: compiler-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
- run: yarn install --frozen-lockfile
|
||||
- name: Publish packages to npm
|
||||
run: |
|
||||
|
||||
@@ -46,8 +46,9 @@ jobs:
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: compiler-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: compiler-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn workspace babel-plugin-react-compiler lint
|
||||
|
||||
@@ -66,8 +67,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: compiler-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: compiler-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn workspace babel-plugin-react-compiler jest
|
||||
|
||||
@@ -90,8 +92,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: compiler-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: compiler-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: xvfb-run -a yarn workspace ${{ matrix.workspace_name }} test
|
||||
if: runner.os == 'Linux' && matrix.workspace_name == 'react-forgive'
|
||||
|
||||
@@ -29,8 +29,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-release-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-release-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -63,8 +64,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -120,8 +122,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- run: yarn install --frozen-lockfile
|
||||
- name: Restore all archived build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
@@ -154,8 +157,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- run: yarn install --frozen-lockfile
|
||||
- name: Restore all archived build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
@@ -55,8 +55,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -79,8 +80,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -105,8 +107,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -153,16 +156,21 @@ jobs:
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
cache-dependency-path: |
|
||||
yarn.lock
|
||||
compiler/yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-and-compiler-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn install --frozen-lockfile
|
||||
working-directory: compiler
|
||||
- run: yarn test ${{ matrix.params }} --ci --shard=${{ matrix.shard }}
|
||||
|
||||
# ----- BUILD -----
|
||||
@@ -183,7 +191,9 @@ jobs:
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
cache-dependency-path: |
|
||||
yarn.lock
|
||||
compiler/yarn.lock
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
@@ -192,11 +202,14 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-and-compiler-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn install --frozen-lockfile
|
||||
working-directory: compiler
|
||||
- run: yarn build --index=${{ matrix.worker_id }} --total=20 --r=${{ matrix.release_channel }} --ci
|
||||
env:
|
||||
CI: github
|
||||
@@ -261,16 +274,21 @@ jobs:
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
cache-dependency-path: |
|
||||
yarn.lock
|
||||
compiler/yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-and-compiler-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn install --frozen-lockfile
|
||||
working-directory: compiler
|
||||
- name: Restore archived build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
@@ -298,8 +316,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -345,8 +364,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -380,8 +400,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -412,8 +433,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: fixtures_dom-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: fixtures_dom-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -455,8 +477,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: fixtures_flight-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: fixtures_flight-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -517,8 +540,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -568,8 +592,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -605,8 +630,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
|
||||
@@ -73,8 +73,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-release-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-release-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
|
||||
@@ -35,16 +35,21 @@ jobs:
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
cache-dependency-path: |
|
||||
yarn.lock
|
||||
compiler/yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "node_modules"
|
||||
key: runtime-eslint_e2e-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-and-compiler-eslint_e2e-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn install --frozen-lockfile
|
||||
working-directory: compiler
|
||||
- name: Build plugin
|
||||
working-directory: fixtures/eslint-v${{ matrix.eslint_major }}
|
||||
run: node build.mjs
|
||||
|
||||
@@ -39,8 +39,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-release-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-release-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
|
||||
@@ -71,8 +71,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-release-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-release-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
|
||||
@@ -28,8 +28,9 @@ jobs:
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: shared-lint-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: shared-lint-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -48,8 +49,9 @@ jobs:
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: shared-lint-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: shared-lint-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -68,8 +70,9 @@ jobs:
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: shared-lint-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: shared-lint-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -88,8 +91,9 @@ jobs:
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: shared-lint-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: shared-lint-node_modules-v5-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
|
||||
+198
-30
@@ -7,21 +7,27 @@ import {
|
||||
Set_intersect,
|
||||
Set_union,
|
||||
getOrInsertDefault,
|
||||
getOrInsertWith,
|
||||
} from '../Utils/utils';
|
||||
import {
|
||||
BasicBlock,
|
||||
BlockId,
|
||||
DependencyPathEntry,
|
||||
GeneratedSource,
|
||||
getHookKind,
|
||||
HIRFunction,
|
||||
Identifier,
|
||||
IdentifierId,
|
||||
InstructionId,
|
||||
InstructionValue,
|
||||
LoweredFunction,
|
||||
Place,
|
||||
PropertyLiteral,
|
||||
ReactiveScopeDependency,
|
||||
ScopeId,
|
||||
ValidatedIdentifier,
|
||||
} from './HIR';
|
||||
import {eachInstructionOperand, eachInstructionValueOperand} from './visitors';
|
||||
|
||||
const DEBUG_PRINT = false;
|
||||
|
||||
@@ -112,6 +118,9 @@ export function collectHoistablePropertyLoads(
|
||||
hoistableFromOptionals,
|
||||
registry,
|
||||
nestedFnImmutableContext: null,
|
||||
fnUsages: fn.env.config.enableTreatFunctionDepsAsConditional
|
||||
? new Map()
|
||||
: mapFunctionExpressionsToEscapingBlocks(fn),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -127,6 +136,11 @@ type CollectHoistablePropertyLoadsContext = {
|
||||
* but are currently kept separate for readability.
|
||||
*/
|
||||
nestedFnImmutableContext: ReadonlySet<IdentifierId> | null;
|
||||
/**
|
||||
* Mapping of functions declared within a traversal context to their
|
||||
* (valid) usage sites, which will have hoistable property loads added
|
||||
*/
|
||||
fnUsages: ReadonlyMap<LoweredFunction, Set<BlockId>>;
|
||||
};
|
||||
function collectHoistablePropertyLoadsImpl(
|
||||
fn: HIRFunction,
|
||||
@@ -338,7 +352,13 @@ function collectNonNullsInBlocks(
|
||||
context.registry.getOrCreateIdentifier(identifier),
|
||||
);
|
||||
}
|
||||
const nodes = new Map<BlockId, BlockInfo>();
|
||||
const nodes = new Map<
|
||||
BlockId,
|
||||
{
|
||||
block: BasicBlock;
|
||||
assumedNonNullObjects: Set<PropertyPathNode>;
|
||||
}
|
||||
>();
|
||||
for (const [_, block] of fn.body.blocks) {
|
||||
const assumedNonNullObjects = new Set<PropertyPathNode>(
|
||||
knownNonNullIdentifiers,
|
||||
@@ -358,40 +378,68 @@ function collectNonNullsInBlocks(
|
||||
) {
|
||||
assumedNonNullObjects.add(maybeNonNull);
|
||||
}
|
||||
if (
|
||||
(instr.value.kind === 'FunctionExpression' ||
|
||||
instr.value.kind === 'ObjectMethod') &&
|
||||
!fn.env.config.enableTreatFunctionDepsAsConditional
|
||||
) {
|
||||
if (instr.value.kind === 'FunctionExpression') {
|
||||
/**
|
||||
* What are reasonable semantics here?
|
||||
* Risky
|
||||
* - only treat named fns as unconditionally hoistable
|
||||
*
|
||||
* Conservative
|
||||
*/
|
||||
const innerFn = instr.value.loweredFunc;
|
||||
const innerHoistableMap = collectHoistablePropertyLoadsImpl(
|
||||
innerFn.func,
|
||||
{
|
||||
...context,
|
||||
nestedFnImmutableContext:
|
||||
context.nestedFnImmutableContext ??
|
||||
new Set(
|
||||
innerFn.func.context
|
||||
.filter(place =>
|
||||
isImmutableAtInstr(place.identifier, instr.id, context),
|
||||
)
|
||||
.map(place => place.identifier.id),
|
||||
),
|
||||
},
|
||||
);
|
||||
const innerHoistables = assertNonNull(
|
||||
innerHoistableMap.get(innerFn.func.body.entry),
|
||||
);
|
||||
for (const entry of innerHoistables.assumedNonNullObjects) {
|
||||
assumedNonNullObjects.add(entry);
|
||||
const resultBlocks = context.fnUsages.get(innerFn);
|
||||
if (resultBlocks != null) {
|
||||
const innerHoistableMap = collectHoistablePropertyLoadsImpl(
|
||||
innerFn.func,
|
||||
{
|
||||
...context,
|
||||
nestedFnImmutableContext:
|
||||
context.nestedFnImmutableContext ??
|
||||
new Set(
|
||||
innerFn.func.context
|
||||
.filter(place =>
|
||||
isImmutableAtInstr(place.identifier, instr.id, context),
|
||||
)
|
||||
.map(place => place.identifier.id),
|
||||
),
|
||||
fnUsages: fn.env.config.enableTreatFunctionDepsAsConditional
|
||||
? new Map()
|
||||
: mapFunctionExpressionsToEscapingBlocks(innerFn.func),
|
||||
},
|
||||
);
|
||||
const innerHoistables = assertNonNull(
|
||||
innerHoistableMap.get(innerFn.func.body.entry),
|
||||
);
|
||||
for (const innerBlock of resultBlocks) {
|
||||
let innerNonNulls;
|
||||
if (innerBlock === block.id) {
|
||||
innerNonNulls = assumedNonNullObjects;
|
||||
} else {
|
||||
innerNonNulls = getOrInsertWith(nodes, innerBlock, () => ({
|
||||
block: assertNonNull(fn.body.blocks.get(innerBlock)),
|
||||
assumedNonNullObjects: new Set(),
|
||||
})).assumedNonNullObjects;
|
||||
}
|
||||
for (const entry of innerHoistables.assumedNonNullObjects) {
|
||||
innerNonNulls.add(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nodes.set(block.id, {
|
||||
block,
|
||||
assumedNonNullObjects,
|
||||
});
|
||||
const maybeNode = nodes.get(block.id);
|
||||
if (maybeNode != null) {
|
||||
// merge
|
||||
for (const entry of assumedNonNullObjects) {
|
||||
maybeNode.assumedNonNullObjects.add(entry);
|
||||
}
|
||||
} else {
|
||||
nodes.set(block.id, {
|
||||
block,
|
||||
assumedNonNullObjects,
|
||||
});
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
@@ -591,3 +639,123 @@ function reduceMaybeOptionalChains(
|
||||
}
|
||||
} while (changed);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* const foo = function() { ... } // this matches
|
||||
* arr.map(function() { ... }) // this does not match
|
||||
*
|
||||
* What about function expressions that just escape to other functions?
|
||||
*
|
||||
* For both below examples, cb1 should be hoistable only to if-cond block
|
||||
* ```js
|
||||
* function useFoo(...) {
|
||||
* const cb1 = function() { ... };
|
||||
* const cb2 = function() { if (cond) cb1() };
|
||||
* return cb2;
|
||||
* }
|
||||
* ```
|
||||
* ```js
|
||||
* function useFoo(...) {
|
||||
* const cb1 = function() { ... };
|
||||
* const cb2 = function() { if (cond) return cb1; };
|
||||
* return cb2;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
function mapFunctionExpressionsToEscapingBlocks(
|
||||
fn: HIRFunction,
|
||||
): ReadonlyMap<LoweredFunction, Set<BlockId>> {
|
||||
/**
|
||||
* Step 1: gather all function expressions and known ssa'd aliases
|
||||
*/
|
||||
const temporaries = new Map<
|
||||
IdentifierId,
|
||||
{fn: LoweredFunction; usage: Set<BlockId>}
|
||||
>();
|
||||
const validUsages = new Set<Place>();
|
||||
|
||||
for (const block of fn.body.blocks.values()) {
|
||||
for (const {lvalue, value} of block.instructions) {
|
||||
/**
|
||||
* Only match function expressions which can have guaranteed ssa.
|
||||
*/
|
||||
if (value.kind === 'FunctionExpression') {
|
||||
temporaries.set(lvalue.identifier.id, {
|
||||
fn: value.loweredFunc,
|
||||
usage: new Set(),
|
||||
});
|
||||
} else if (value.kind === 'StoreLocal') {
|
||||
const lvalue = value.lvalue.place.identifier;
|
||||
const maybeLoweredFunc = temporaries.get(value.value.identifier.id);
|
||||
if (
|
||||
lvalue.name != null &&
|
||||
lvalue.name.kind === 'named' &&
|
||||
maybeLoweredFunc != null
|
||||
) {
|
||||
temporaries.set(lvalue.id, maybeLoweredFunc);
|
||||
validUsages.add(value.value);
|
||||
}
|
||||
} else if (value.kind === 'LoadLocal') {
|
||||
const maybeLoweredFunc = temporaries.get(value.place.identifier.id);
|
||||
if (maybeLoweredFunc != null) {
|
||||
temporaries.set(lvalue.identifier.id, maybeLoweredFunc);
|
||||
validUsages.add(value.place);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Step 2: Forward pass to do best-effort "escape analysis"
|
||||
*/
|
||||
for (const block of fn.body.blocks.values()) {
|
||||
for (const {value} of block.instructions) {
|
||||
if (value.kind === 'CallExpression') {
|
||||
const callee = value.callee;
|
||||
const maybeHook = getHookKind(fn.env, callee.identifier);
|
||||
const maybeLoweredFunc = temporaries.get(callee.identifier.id);
|
||||
if (maybeLoweredFunc != null) {
|
||||
// Direct calls
|
||||
maybeLoweredFunc.usage.add(block.id);
|
||||
} else if (maybeHook != null) {
|
||||
// Arguments to hooks
|
||||
for (const arg of value.args.filter(
|
||||
arg => arg.kind === 'Identifier',
|
||||
) as Array<Place>) {
|
||||
const maybeLoweredFunc = temporaries.get(arg.identifier.id);
|
||||
if (maybeLoweredFunc != null) {
|
||||
maybeLoweredFunc.usage.add(block.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (value.kind === 'JsxExpression') {
|
||||
/* Match jsx attributes */
|
||||
for (const attr of value.props) {
|
||||
if (attr.kind === 'JsxSpreadAttribute') {
|
||||
continue;
|
||||
}
|
||||
const maybeLoweredFunc = temporaries.get(attr.place.identifier.id);
|
||||
if (maybeLoweredFunc != null) {
|
||||
maybeLoweredFunc.usage.add(block.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (block.terminal.kind === 'return') {
|
||||
const maybeLoweredFunc = temporaries.get(
|
||||
block.terminal.value.identifier.id,
|
||||
);
|
||||
if (maybeLoweredFunc != null) {
|
||||
maybeLoweredFunc.usage.add(block.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const map = new Map<LoweredFunction, Set<BlockId>>();
|
||||
for (const {fn, usage} of temporaries.values()) {
|
||||
if (!map.has(fn)) {
|
||||
map.set(fn, usage);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function useFoo({arr}) {
|
||||
return arr.map(e => arr[0].value + e.value);
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{arr: []}],
|
||||
sequentialRenders: [{arr: []}, {arr: [{value: 1}, {value: 2}]}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
function useFoo(t0) {
|
||||
const $ = _c(4);
|
||||
const { arr } = t0;
|
||||
let t1;
|
||||
if ($[0] !== arr) {
|
||||
let t2;
|
||||
if ($[2] !== arr[0]) {
|
||||
t2 = (e) => arr[0].value + e.value;
|
||||
$[2] = arr[0];
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
}
|
||||
t1 = arr.map(t2);
|
||||
$[0] = arr;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{ arr: [] }],
|
||||
sequentialRenders: [{ arr: [] }, { arr: [{ value: 1 }, { value: 2 }] }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) []
|
||||
[2,3]
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
function useFoo({arr}) {
|
||||
return arr.map(e => arr[0].value + e.value);
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{arr: []}],
|
||||
sequentialRenders: [{arr: []}, {arr: [{value: 1}, {value: 2}]}],
|
||||
};
|
||||
+2
-2
@@ -56,9 +56,9 @@ function useFoo(t0) {
|
||||
setPropertyByKey(obj, "arr", arr);
|
||||
const obj_alias = obj;
|
||||
let t2;
|
||||
if ($[2] !== obj_alias.arr.length) {
|
||||
if ($[2] !== obj_alias) {
|
||||
t2 = () => obj_alias.arr.length;
|
||||
$[2] = obj_alias.arr.length;
|
||||
$[2] = obj_alias;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
|
||||
+2
-2
@@ -23,11 +23,11 @@ import { c as _c } from "react/compiler-runtime";
|
||||
function Component(props) {
|
||||
const $ = _c(4);
|
||||
let t0;
|
||||
if ($[0] !== props.name) {
|
||||
if ($[0] !== props) {
|
||||
t0 = function () {
|
||||
return <div>{props.name}</div>;
|
||||
};
|
||||
$[0] = props.name;
|
||||
$[0] = props;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @validatePreserveExistingMemoizationGuarantees
|
||||
import {useMemo} from 'react';
|
||||
|
||||
function useHook(maybeRef, shouldRead) {
|
||||
return useMemo(() => {
|
||||
return () => [maybeRef.current];
|
||||
}, [shouldRead, maybeRef]);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
3 |
|
||||
4 | function useHook(maybeRef, shouldRead) {
|
||||
> 5 | return useMemo(() => {
|
||||
| ^^^^^^^
|
||||
> 6 | return () => [maybeRef.current];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 7 | }, [shouldRead, maybeRef]);
|
||||
| ^^^^ CannotPreserveMemoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected (5:7)
|
||||
8 | }
|
||||
9 |
|
||||
```
|
||||
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @validatePreserveExistingMemoizationGuarantees
|
||||
import {useMemo} from 'react';
|
||||
|
||||
function useHook(maybeRef, shouldRead) {
|
||||
return useMemo(() => {
|
||||
return () => [maybeRef.current];
|
||||
}, [shouldRead, maybeRef]);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @validatePreserveExistingMemoizationGuarantees
|
||||
import { useMemo } from "react";
|
||||
|
||||
function useHook(maybeRef, shouldRead) {
|
||||
const $ = _c(2);
|
||||
let t0;
|
||||
let t1;
|
||||
if ($[0] !== maybeRef) {
|
||||
t1 = () => [maybeRef.current];
|
||||
$[0] = maybeRef;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
t0 = t1;
|
||||
return t0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: exception) Fixture not implemented
|
||||
+2
-2
@@ -41,9 +41,9 @@ function useFoo(t0) {
|
||||
local = $[1];
|
||||
}
|
||||
let t1;
|
||||
if ($[2] !== local.b.c) {
|
||||
if ($[2] !== local) {
|
||||
t1 = () => [() => local.b.c];
|
||||
$[2] = local.b.c;
|
||||
$[2] = local;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
|
||||
+2
-2
@@ -34,13 +34,13 @@ function useFoo(t0) {
|
||||
const $ = _c(4);
|
||||
const { a } = t0;
|
||||
let t1;
|
||||
if ($[0] !== a.b.c) {
|
||||
if ($[0] !== a) {
|
||||
t1 = {
|
||||
fn() {
|
||||
return identity(a.b.c);
|
||||
},
|
||||
};
|
||||
$[0] = a.b.c;
|
||||
$[0] = a;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
|
||||
+2
-2
@@ -51,7 +51,7 @@ import { identity } from "shared-runtime";
|
||||
function Component(props) {
|
||||
const $ = _c(4);
|
||||
let x;
|
||||
if ($[0] !== props.cond) {
|
||||
if ($[0] !== props) {
|
||||
const f = () => {
|
||||
if (props.cond) {
|
||||
x = 1;
|
||||
@@ -62,7 +62,7 @@ function Component(props) {
|
||||
|
||||
const f2 = identity(f);
|
||||
f2();
|
||||
$[0] = props.cond;
|
||||
$[0] = props;
|
||||
$[1] = x;
|
||||
} else {
|
||||
x = $[1];
|
||||
|
||||
+2
-2
@@ -82,9 +82,9 @@ function Component(t0) {
|
||||
contextVar = $[2];
|
||||
}
|
||||
let t1;
|
||||
if ($[3] !== contextVar.val) {
|
||||
if ($[3] !== contextVar) {
|
||||
t1 = { cb: () => contextVar.val * 4 };
|
||||
$[3] = contextVar.val;
|
||||
$[3] = contextVar;
|
||||
$[4] = t1;
|
||||
} else {
|
||||
t1 = $[4];
|
||||
|
||||
+2
-2
@@ -43,7 +43,7 @@ const t0 = "module_t0";
|
||||
const c_0 = "module_c_0";
|
||||
function useFoo(props) {
|
||||
const $0 = _c(2);
|
||||
const c_00 = $0[0] !== props.value;
|
||||
const c_00 = $0[0] !== props;
|
||||
let t1;
|
||||
if (c_00) {
|
||||
const a = {
|
||||
@@ -61,7 +61,7 @@ function useFoo(props) {
|
||||
};
|
||||
|
||||
t1 = a.foo().bar();
|
||||
$0[0] = props.value;
|
||||
$0[0] = props;
|
||||
$0[1] = t1;
|
||||
} else {
|
||||
t1 = $0[1];
|
||||
|
||||
+10
-15
@@ -35,7 +35,7 @@ function Component(props) {
|
||||
import { c as _c } from "react/compiler-runtime"; // @enableTransitivelyFreezeFunctionExpressions:false
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(9);
|
||||
const $ = _c(7);
|
||||
const item = useMutable(props.itemId);
|
||||
const dispatch = useDispatch();
|
||||
useFreeze(dispatch);
|
||||
@@ -51,7 +51,8 @@ function Component(props) {
|
||||
}
|
||||
const exit = t0;
|
||||
let t1;
|
||||
if ($[2] !== exit || $[3] !== item.value) {
|
||||
let t2;
|
||||
if ($[2] !== exit || $[3] !== item) {
|
||||
t1 = () => {
|
||||
const cleanup = GlobalEventEmitter.addListener("onInput", () => {
|
||||
if (item.value) {
|
||||
@@ -60,30 +61,24 @@ function Component(props) {
|
||||
});
|
||||
return () => cleanup.remove();
|
||||
};
|
||||
t2 = [exit, item];
|
||||
$[2] = exit;
|
||||
$[3] = item.value;
|
||||
$[3] = item;
|
||||
$[4] = t1;
|
||||
$[5] = t2;
|
||||
} else {
|
||||
t1 = $[4];
|
||||
}
|
||||
let t2;
|
||||
if ($[5] !== exit || $[6] !== item) {
|
||||
t2 = [exit, item];
|
||||
$[5] = exit;
|
||||
$[6] = item;
|
||||
$[7] = t2;
|
||||
} else {
|
||||
t2 = $[7];
|
||||
t2 = $[5];
|
||||
}
|
||||
useEffect(t1, t2);
|
||||
|
||||
maybeMutate(item);
|
||||
let t3;
|
||||
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t3 = <div />;
|
||||
$[8] = t3;
|
||||
$[6] = t3;
|
||||
} else {
|
||||
t3 = $[8];
|
||||
t3 = $[6];
|
||||
}
|
||||
return t3;
|
||||
}
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@
|
||||
"testRegex": "/scripts/jest/dont-run-jest-directly\\.js$"
|
||||
},
|
||||
"scripts": {
|
||||
"prebuild": "yarn --cwd compiler install --frozen-lockfile && ./scripts/react-compiler/link-compiler.sh",
|
||||
"prebuild": "./scripts/react-compiler/link-compiler.sh",
|
||||
"build": "node ./scripts/rollup/build-all-release-channels.js",
|
||||
"build-for-devtools": "cross-env RELEASE_CHANNEL=experimental yarn build react/index,react/jsx,react/compiler-runtime,react-dom/index,react-dom/client,react-dom/unstable_testing,react-dom/test-utils,react-is,react-debug-tools,scheduler,react-test-renderer,react-refresh,react-art --type=NODE",
|
||||
"build-for-devtools-dev": "yarn build-for-devtools --type=NODE_DEV",
|
||||
|
||||
+1
@@ -878,6 +878,7 @@ export function createFiberFromViewTransition(
|
||||
const instance: ViewTransitionState = {
|
||||
autoName: null,
|
||||
paired: null,
|
||||
clones: null,
|
||||
ref: null,
|
||||
};
|
||||
fiber.stateNode = instance;
|
||||
|
||||
+718
-111
File diff suppressed because it is too large
Load Diff
+112
-86
@@ -71,15 +71,40 @@ export let viewTransitionCancelableChildren: null | Array<
|
||||
Instance | string | Props,
|
||||
> = null; // tupled array where each entry is [instance: Instance, oldName: string, props: Props]
|
||||
|
||||
export function setViewTransitionCancelableChildren(
|
||||
children: null | Array<Instance | string | Props>,
|
||||
export function pushViewTransitionCancelableScope(): null | Array<
|
||||
Instance | string | Props,
|
||||
> {
|
||||
const prevChildren = viewTransitionCancelableChildren;
|
||||
viewTransitionCancelableChildren = null;
|
||||
return prevChildren;
|
||||
}
|
||||
|
||||
export function popViewTransitionCancelableScope(
|
||||
prevChildren: null | Array<Instance | string | Props>,
|
||||
): void {
|
||||
viewTransitionCancelableChildren = children;
|
||||
viewTransitionCancelableChildren = prevChildren;
|
||||
}
|
||||
|
||||
let viewTransitionHostInstanceIdx = 0;
|
||||
|
||||
function applyViewTransitionToHostInstances(
|
||||
export function applyViewTransitionToHostInstances(
|
||||
child: null | Fiber,
|
||||
name: string,
|
||||
className: ?string,
|
||||
collectMeasurements: null | Array<InstanceMeasurement>,
|
||||
stopAtNestedViewTransitions: boolean,
|
||||
): boolean {
|
||||
viewTransitionHostInstanceIdx = 0;
|
||||
return applyViewTransitionToHostInstancesRecursive(
|
||||
child,
|
||||
name,
|
||||
className,
|
||||
collectMeasurements,
|
||||
stopAtNestedViewTransitions,
|
||||
);
|
||||
}
|
||||
|
||||
function applyViewTransitionToHostInstancesRecursive(
|
||||
child: null | Fiber,
|
||||
name: string,
|
||||
className: ?string,
|
||||
@@ -128,7 +153,7 @@ function applyViewTransitionToHostInstances(
|
||||
// inner most one is the one that handles the update.
|
||||
} else {
|
||||
if (
|
||||
applyViewTransitionToHostInstances(
|
||||
applyViewTransitionToHostInstancesRecursive(
|
||||
child.child,
|
||||
name,
|
||||
className,
|
||||
@@ -207,7 +232,6 @@ function commitAppearingPairViewTransitions(placement: Fiber): void {
|
||||
if (className !== 'none') {
|
||||
// We found a new appearing view transition with the same name as this deletion.
|
||||
// We'll transition between them.
|
||||
viewTransitionHostInstanceIdx = 0;
|
||||
const inViewport = applyViewTransitionToHostInstances(
|
||||
child.child,
|
||||
name,
|
||||
@@ -242,7 +266,6 @@ export function commitEnterViewTransitions(placement: Fiber): void {
|
||||
state.paired ? props.share : props.enter,
|
||||
);
|
||||
if (className !== 'none') {
|
||||
viewTransitionHostInstanceIdx = 0;
|
||||
const inViewport = applyViewTransitionToHostInstances(
|
||||
placement.child,
|
||||
name,
|
||||
@@ -310,7 +333,6 @@ function commitDeletedPairViewTransitions(deletion: Fiber): void {
|
||||
);
|
||||
if (className !== 'none') {
|
||||
// We found a new appearing view transition with the same name as this deletion.
|
||||
viewTransitionHostInstanceIdx = 0;
|
||||
const inViewport = applyViewTransitionToHostInstances(
|
||||
child.child,
|
||||
name,
|
||||
@@ -361,7 +383,6 @@ export function commitExitViewTransitions(deletion: Fiber): void {
|
||||
pair !== undefined ? props.share : props.exit,
|
||||
);
|
||||
if (className !== 'none') {
|
||||
viewTransitionHostInstanceIdx = 0;
|
||||
const inViewport = applyViewTransitionToHostInstances(
|
||||
deletion.child,
|
||||
name,
|
||||
@@ -449,7 +470,6 @@ export function commitBeforeUpdateViewTransition(
|
||||
return;
|
||||
}
|
||||
}
|
||||
viewTransitionHostInstanceIdx = 0;
|
||||
applyViewTransitionToHostInstances(
|
||||
current.child,
|
||||
oldName,
|
||||
@@ -472,7 +492,6 @@ export function commitNestedViewTransitions(changedParent: Fiber): void {
|
||||
props.layout,
|
||||
);
|
||||
if (className !== 'none') {
|
||||
viewTransitionHostInstanceIdx = 0;
|
||||
applyViewTransitionToHostInstances(
|
||||
child.child,
|
||||
name,
|
||||
@@ -514,37 +533,20 @@ function restorePairedViewTransitions(parent: Fiber): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function restoreEnterViewTransitions(placement: Fiber): void {
|
||||
if (placement.tag === ViewTransitionComponent) {
|
||||
const instance: ViewTransitionState = placement.stateNode;
|
||||
export function restoreEnterOrExitViewTransitions(fiber: Fiber): void {
|
||||
if (fiber.tag === ViewTransitionComponent) {
|
||||
const instance: ViewTransitionState = fiber.stateNode;
|
||||
instance.paired = null;
|
||||
restoreViewTransitionOnHostInstances(placement.child, false);
|
||||
restorePairedViewTransitions(placement);
|
||||
} else if ((placement.subtreeFlags & ViewTransitionStatic) !== NoFlags) {
|
||||
let child = placement.child;
|
||||
restoreViewTransitionOnHostInstances(fiber.child, false);
|
||||
restorePairedViewTransitions(fiber);
|
||||
} else if ((fiber.subtreeFlags & ViewTransitionStatic) !== NoFlags) {
|
||||
let child = fiber.child;
|
||||
while (child !== null) {
|
||||
restoreEnterViewTransitions(child);
|
||||
restoreEnterOrExitViewTransitions(child);
|
||||
child = child.sibling;
|
||||
}
|
||||
} else {
|
||||
restorePairedViewTransitions(placement);
|
||||
}
|
||||
}
|
||||
|
||||
export function restoreExitViewTransitions(deletion: Fiber): void {
|
||||
if (deletion.tag === ViewTransitionComponent) {
|
||||
const instance: ViewTransitionState = deletion.stateNode;
|
||||
instance.paired = null;
|
||||
restoreViewTransitionOnHostInstances(deletion.child, false);
|
||||
restorePairedViewTransitions(deletion);
|
||||
} else if ((deletion.subtreeFlags & ViewTransitionStatic) !== NoFlags) {
|
||||
let child = deletion.child;
|
||||
while (child !== null) {
|
||||
restoreExitViewTransitions(child);
|
||||
child = child.sibling;
|
||||
}
|
||||
} else {
|
||||
restorePairedViewTransitions(deletion);
|
||||
restorePairedViewTransitions(fiber);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,9 +572,22 @@ export function restoreNestedViewTransitions(changedParent: Fiber): void {
|
||||
}
|
||||
}
|
||||
|
||||
function cancelViewTransitionHostInstances(
|
||||
currentViewTransition: Fiber,
|
||||
export function cancelViewTransitionHostInstances(
|
||||
child: null | Fiber,
|
||||
oldName: string,
|
||||
stopAtNestedViewTransitions: boolean,
|
||||
): void {
|
||||
viewTransitionHostInstanceIdx = 0;
|
||||
cancelViewTransitionHostInstancesRecursive(
|
||||
child,
|
||||
oldName,
|
||||
stopAtNestedViewTransitions,
|
||||
);
|
||||
}
|
||||
|
||||
function cancelViewTransitionHostInstancesRecursive(
|
||||
child: null | Fiber,
|
||||
oldName: string,
|
||||
stopAtNestedViewTransitions: boolean,
|
||||
): void {
|
||||
if (!supportsMutation) {
|
||||
@@ -581,10 +596,6 @@ function cancelViewTransitionHostInstances(
|
||||
while (child !== null) {
|
||||
if (child.tag === HostComponent) {
|
||||
const instance: Instance = child.stateNode;
|
||||
const oldName = getViewTransitionName(
|
||||
currentViewTransition.memoizedProps,
|
||||
currentViewTransition.stateNode,
|
||||
);
|
||||
if (viewTransitionCancelableChildren === null) {
|
||||
viewTransitionCancelableChildren = [];
|
||||
}
|
||||
@@ -606,9 +617,9 @@ function cancelViewTransitionHostInstances(
|
||||
// Skip any nested view transitions for updates since in that case the
|
||||
// inner most one is the one that handles the update.
|
||||
} else {
|
||||
cancelViewTransitionHostInstances(
|
||||
currentViewTransition,
|
||||
cancelViewTransitionHostInstancesRecursive(
|
||||
child.child,
|
||||
oldName,
|
||||
stopAtNestedViewTransitions,
|
||||
);
|
||||
}
|
||||
@@ -616,11 +627,32 @@ function cancelViewTransitionHostInstances(
|
||||
}
|
||||
}
|
||||
|
||||
function measureViewTransitionHostInstances(
|
||||
currentViewTransition: Fiber,
|
||||
export function measureViewTransitionHostInstances(
|
||||
parentViewTransition: Fiber,
|
||||
child: null | Fiber,
|
||||
name: string,
|
||||
newName: string,
|
||||
oldName: string,
|
||||
className: ?string,
|
||||
previousMeasurements: null | Array<InstanceMeasurement>,
|
||||
stopAtNestedViewTransitions: boolean,
|
||||
): boolean {
|
||||
viewTransitionHostInstanceIdx = 0;
|
||||
return measureViewTransitionHostInstancesRecursive(
|
||||
parentViewTransition,
|
||||
child,
|
||||
newName,
|
||||
oldName,
|
||||
className,
|
||||
previousMeasurements,
|
||||
stopAtNestedViewTransitions,
|
||||
);
|
||||
}
|
||||
|
||||
function measureViewTransitionHostInstancesRecursive(
|
||||
parentViewTransition: Fiber,
|
||||
child: null | Fiber,
|
||||
newName: string,
|
||||
oldName: string,
|
||||
className: ?string,
|
||||
previousMeasurements: null | Array<InstanceMeasurement>,
|
||||
stopAtNestedViewTransitions: boolean,
|
||||
@@ -671,10 +703,10 @@ function measureViewTransitionHostInstances(
|
||||
applyViewTransitionName(
|
||||
instance,
|
||||
viewTransitionHostInstanceIdx === 0
|
||||
? name
|
||||
? newName
|
||||
: // If we have multiple Host Instances below, we add a suffix to the name to give
|
||||
// each one a unique name.
|
||||
name + '_' + viewTransitionHostInstanceIdx,
|
||||
newName + '_' + viewTransitionHostInstanceIdx,
|
||||
className,
|
||||
);
|
||||
}
|
||||
@@ -684,10 +716,6 @@ function measureViewTransitionHostInstances(
|
||||
// animating it. However, in the current model this only works if the parent also
|
||||
// doesn't animate. So we have to queue these and wait until we complete the parent
|
||||
// to cancel them.
|
||||
const oldName = getViewTransitionName(
|
||||
currentViewTransition.memoizedProps,
|
||||
currentViewTransition.stateNode,
|
||||
);
|
||||
if (viewTransitionCancelableChildren === null) {
|
||||
viewTransitionCancelableChildren = [];
|
||||
}
|
||||
@@ -713,11 +741,11 @@ function measureViewTransitionHostInstances(
|
||||
parentViewTransition.flags |= child.flags & AffectedParentLayout;
|
||||
} else {
|
||||
if (
|
||||
measureViewTransitionHostInstances(
|
||||
currentViewTransition,
|
||||
measureViewTransitionHostInstancesRecursive(
|
||||
parentViewTransition,
|
||||
child.child,
|
||||
name,
|
||||
newName,
|
||||
oldName,
|
||||
className,
|
||||
previousMeasurements,
|
||||
stopAtNestedViewTransitions,
|
||||
@@ -736,6 +764,11 @@ export function measureUpdateViewTransition(
|
||||
finishedWork: Fiber,
|
||||
): boolean {
|
||||
const props: ViewTransitionProps = finishedWork.memoizedProps;
|
||||
const newName = getViewTransitionName(props, finishedWork.stateNode);
|
||||
const oldName = getViewTransitionName(
|
||||
current.memoizedProps,
|
||||
current.stateNode,
|
||||
);
|
||||
const updateClassName: ?string = getViewTransitionClassName(
|
||||
props.className,
|
||||
props.update,
|
||||
@@ -762,24 +795,21 @@ export function measureUpdateViewTransition(
|
||||
if (layoutClassName === 'none') {
|
||||
// If we did not update, then all changes are considered a layout. We'll
|
||||
// attempt to cancel.
|
||||
viewTransitionHostInstanceIdx = 0;
|
||||
cancelViewTransitionHostInstances(current, finishedWork.child, true);
|
||||
cancelViewTransitionHostInstances(finishedWork.child, oldName, true);
|
||||
return false;
|
||||
}
|
||||
// We didn't update but we might still apply layout so we measure each
|
||||
// instance to see if it moved or resized.
|
||||
className = layoutClassName;
|
||||
}
|
||||
const name = getViewTransitionName(props, finishedWork.stateNode);
|
||||
// If nothing changed due to a mutation, or children changing size
|
||||
// and the measurements end up unchanged, we should restore it to not animate.
|
||||
viewTransitionHostInstanceIdx = 0;
|
||||
const previousMeasurements = current.memoizedState;
|
||||
const inViewport = measureViewTransitionHostInstances(
|
||||
current,
|
||||
finishedWork,
|
||||
finishedWork.child,
|
||||
name,
|
||||
newName,
|
||||
oldName,
|
||||
className,
|
||||
previousMeasurements,
|
||||
true,
|
||||
@@ -799,29 +829,25 @@ export function measureNestedViewTransitions(changedParent: Fiber): void {
|
||||
let child = changedParent.child;
|
||||
while (child !== null) {
|
||||
if (child.tag === ViewTransitionComponent) {
|
||||
const current = child.alternate;
|
||||
if (current !== null) {
|
||||
const props: ViewTransitionProps = child.memoizedProps;
|
||||
const name = getViewTransitionName(props, child.stateNode);
|
||||
const className: ?string = getViewTransitionClassName(
|
||||
props.className,
|
||||
props.layout,
|
||||
);
|
||||
viewTransitionHostInstanceIdx = 0;
|
||||
const inViewport = measureViewTransitionHostInstances(
|
||||
current,
|
||||
child,
|
||||
child.child,
|
||||
name,
|
||||
className,
|
||||
child.memoizedState,
|
||||
false,
|
||||
);
|
||||
if ((child.flags & Update) === NoFlags || !inViewport) {
|
||||
// Nothing changed.
|
||||
} else {
|
||||
scheduleViewTransitionEvent(child, props.onLayout);
|
||||
}
|
||||
const props: ViewTransitionProps = child.memoizedProps;
|
||||
const name = getViewTransitionName(props, child.stateNode);
|
||||
const className: ?string = getViewTransitionClassName(
|
||||
props.className,
|
||||
props.layout,
|
||||
);
|
||||
const inViewport = measureViewTransitionHostInstances(
|
||||
child,
|
||||
child.child,
|
||||
name,
|
||||
name, // Since this is unchanged, new and old name is the same.
|
||||
className,
|
||||
child.memoizedState,
|
||||
false,
|
||||
);
|
||||
if ((child.flags & Update) === NoFlags || !inViewport) {
|
||||
// Nothing changed.
|
||||
} else {
|
||||
scheduleViewTransitionEvent(child, props.onLayout);
|
||||
}
|
||||
} else if ((child.subtreeFlags & ViewTransitionStatic) !== NoFlags) {
|
||||
measureNestedViewTransitions(child);
|
||||
|
||||
+11
-12
@@ -246,8 +246,7 @@ import {
|
||||
commitExitViewTransitions,
|
||||
commitBeforeUpdateViewTransition,
|
||||
commitNestedViewTransitions,
|
||||
restoreEnterViewTransitions,
|
||||
restoreExitViewTransitions,
|
||||
restoreEnterOrExitViewTransitions,
|
||||
restoreUpdateViewTransition,
|
||||
restoreNestedViewTransitions,
|
||||
measureUpdateViewTransition,
|
||||
@@ -255,7 +254,8 @@ import {
|
||||
resetAppearingViewTransitions,
|
||||
trackAppearingViewTransition,
|
||||
viewTransitionCancelableChildren,
|
||||
setViewTransitionCancelableChildren,
|
||||
pushViewTransitionCancelableScope,
|
||||
popViewTransitionCancelableScope,
|
||||
} from './ReactFiberCommitViewTransitions';
|
||||
import {
|
||||
viewTransitionMutationContext,
|
||||
@@ -2475,14 +2475,14 @@ function commitAfterMutationEffectsOnFiber(
|
||||
switch (finishedWork.tag) {
|
||||
case HostRoot: {
|
||||
viewTransitionContextChanged = false;
|
||||
setViewTransitionCancelableChildren(null);
|
||||
pushViewTransitionCancelableScope();
|
||||
recursivelyTraverseAfterMutationEffects(root, finishedWork, lanes);
|
||||
if (!viewTransitionContextChanged) {
|
||||
// If we didn't leak any resizing out to the root, we don't have to transition
|
||||
// the root itself. This means that we can now safely cancel any cancellations
|
||||
// that bubbled all the way up.
|
||||
const cancelableChildren = viewTransitionCancelableChildren;
|
||||
setViewTransitionCancelableChildren(null);
|
||||
popViewTransitionCancelableScope(null);
|
||||
if (cancelableChildren !== null) {
|
||||
for (let i = 0; i < cancelableChildren.length; i += 3) {
|
||||
cancelViewTransitionName(
|
||||
@@ -2533,9 +2533,8 @@ function commitAfterMutationEffectsOnFiber(
|
||||
const wasMutated = (finishedWork.flags & Update) !== NoFlags;
|
||||
|
||||
const prevContextChanged = viewTransitionContextChanged;
|
||||
const prevCancelableChildren = viewTransitionCancelableChildren;
|
||||
const prevCancelableChildren = pushViewTransitionCancelableScope();
|
||||
viewTransitionContextChanged = false;
|
||||
setViewTransitionCancelableChildren(null);
|
||||
recursivelyTraverseAfterMutationEffects(root, finishedWork, lanes);
|
||||
|
||||
if (viewTransitionContextChanged) {
|
||||
@@ -2558,7 +2557,7 @@ function commitAfterMutationEffectsOnFiber(
|
||||
prevCancelableChildren,
|
||||
viewTransitionCancelableChildren,
|
||||
);
|
||||
setViewTransitionCancelableChildren(prevCancelableChildren);
|
||||
popViewTransitionCancelableScope(prevCancelableChildren);
|
||||
}
|
||||
// TODO: If this doesn't end up canceled, because a parent animates,
|
||||
// then we should probably issue an event since this instance is part of it.
|
||||
@@ -2572,7 +2571,7 @@ function commitAfterMutationEffectsOnFiber(
|
||||
);
|
||||
|
||||
// If this boundary did update, we cannot cancel its children so those are dropped.
|
||||
setViewTransitionCancelableChildren(prevCancelableChildren);
|
||||
popViewTransitionCancelableScope(prevCancelableChildren);
|
||||
}
|
||||
|
||||
if ((finishedWork.flags & AffectedParentLayout) !== NoFlags) {
|
||||
@@ -3228,7 +3227,7 @@ function commitPassiveMountOnFiber(
|
||||
// This was a new mount. This means we could've triggered an enter animation on
|
||||
// the content. Restore the view transitions if there were any assigned in the
|
||||
// snapshot phase.
|
||||
restoreEnterViewTransitions(finishedWork);
|
||||
restoreEnterOrExitViewTransitions(finishedWork);
|
||||
}
|
||||
|
||||
// When updating this function, also update reconnectPassiveEffects, which does
|
||||
@@ -3529,7 +3528,7 @@ function commitPassiveMountOnFiber(
|
||||
// Content is now hidden but wasn't before. This means we could've
|
||||
// triggered an exit animation on the content. Restore the view
|
||||
// transitions if there were any assigned in the snapshot phase.
|
||||
restoreExitViewTransitions(current);
|
||||
restoreEnterOrExitViewTransitions(current);
|
||||
}
|
||||
if (instance._visibility & OffscreenPassiveEffectsConnected) {
|
||||
// The effects are currently connected. Update them.
|
||||
@@ -3576,7 +3575,7 @@ function commitPassiveMountOnFiber(
|
||||
// Content is now visible but wasn't before. This means we could've
|
||||
// triggered an enter animation on the content. Restore the view
|
||||
// transitions if there were any assigned in the snapshot phase.
|
||||
restoreEnterViewTransitions(finishedWork);
|
||||
restoreEnterOrExitViewTransitions(finishedWork);
|
||||
}
|
||||
if (instance._visibility & OffscreenPassiveEffectsConnected) {
|
||||
// The effects are currently connected. Update them.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
import type {ReactNodeList} from 'shared/ReactTypes';
|
||||
import type {FiberRoot} from './ReactInternalTypes';
|
||||
import type {ViewTransitionInstance} from './ReactFiberConfig';
|
||||
import type {ViewTransitionInstance, Instance} from './ReactFiberConfig';
|
||||
|
||||
import {
|
||||
getWorkInProgressRoot,
|
||||
@@ -45,6 +45,7 @@ export type ViewTransitionProps = {
|
||||
export type ViewTransitionState = {
|
||||
autoName: null | string, // the view-transition-name to use when an explicit one is not specified
|
||||
paired: null | ViewTransitionState, // a temporary state during the commit phase if we have paired this with another instance
|
||||
clones: null | Array<Instance>, // a temporary state during the apply gesture phase if we cloned this boundary
|
||||
ref: null | ViewTransitionInstance, // the current ref instance. This can change through the lifetime of the instance.
|
||||
};
|
||||
|
||||
|
||||
@@ -3927,6 +3927,9 @@ function commitGestureOnRoot(
|
||||
}
|
||||
|
||||
function flushGestureMutations(): void {
|
||||
if (!enableSwipeTransition) {
|
||||
return;
|
||||
}
|
||||
if (pendingEffectsStatus !== PENDING_GESTURE_MUTATION_PHASE) {
|
||||
return;
|
||||
}
|
||||
@@ -3953,6 +3956,9 @@ function flushGestureMutations(): void {
|
||||
}
|
||||
|
||||
function flushGestureAnimations(): void {
|
||||
if (!enableSwipeTransition) {
|
||||
return;
|
||||
}
|
||||
// If we get canceled before we start we might not have applied
|
||||
// mutations yet. We need to apply them first.
|
||||
flushGestureMutations();
|
||||
|
||||
@@ -11,5 +11,4 @@ if [[ "$REACT_CLASS_EQUIVALENCE_TEST" == "true" ]]; then
|
||||
fi
|
||||
|
||||
echo "Building babel-plugin-react-compiler..."
|
||||
yarn --cwd compiler install --frozen-lockfile
|
||||
yarn --cwd compiler workspace babel-plugin-react-compiler build --dts
|
||||
|
||||
Reference in New Issue
Block a user