Skip to content

Commit 6e27e85

Browse files
committed
[compiler] Extract reusable logic for control dominators (#35146)
The next PR needs to check if a block is controlled by a value derived from a ref. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35146). * #35148 * #35147 * __->__ #35146 DiffTrain build for [d6b1a05](d6b1a05)
1 parent b57d73d commit 6e27e85

35 files changed

+166
-162
lines changed

compiled/eslint-plugin-react-hooks/index.js

Lines changed: 80 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -44864,6 +44864,85 @@ function findOptionalPlaces(fn) {
4486444864
return optionals;
4486544865
}
4486644866

44867+
function createControlDominators(fn, isControlVariable) {
44868+
const postDominators = computePostDominatorTree(fn, {
44869+
includeThrowsAsExitNode: false,
44870+
});
44871+
const postDominatorFrontierCache = new Map();
44872+
function isControlledBlock(id) {
44873+
let controlBlocks = postDominatorFrontierCache.get(id);
44874+
if (controlBlocks === undefined) {
44875+
controlBlocks = postDominatorFrontier(fn, postDominators, id);
44876+
postDominatorFrontierCache.set(id, controlBlocks);
44877+
}
44878+
for (const blockId of controlBlocks) {
44879+
const controlBlock = fn.body.blocks.get(blockId);
44880+
switch (controlBlock.terminal.kind) {
44881+
case 'if':
44882+
case 'branch': {
44883+
if (isControlVariable(controlBlock.terminal.test)) {
44884+
return true;
44885+
}
44886+
break;
44887+
}
44888+
case 'switch': {
44889+
if (isControlVariable(controlBlock.terminal.test)) {
44890+
return true;
44891+
}
44892+
for (const case_ of controlBlock.terminal.cases) {
44893+
if (case_.test !== null && isControlVariable(case_.test)) {
44894+
return true;
44895+
}
44896+
}
44897+
break;
44898+
}
44899+
}
44900+
}
44901+
return false;
44902+
}
44903+
return isControlledBlock;
44904+
}
44905+
function postDominatorFrontier(fn, postDominators, targetId) {
44906+
const visited = new Set();
44907+
const frontier = new Set();
44908+
const targetPostDominators = postDominatorsOf(fn, postDominators, targetId);
44909+
for (const blockId of [...targetPostDominators, targetId]) {
44910+
if (visited.has(blockId)) {
44911+
continue;
44912+
}
44913+
visited.add(blockId);
44914+
const block = fn.body.blocks.get(blockId);
44915+
for (const pred of block.preds) {
44916+
if (!targetPostDominators.has(pred)) {
44917+
frontier.add(pred);
44918+
}
44919+
}
44920+
}
44921+
return frontier;
44922+
}
44923+
function postDominatorsOf(fn, postDominators, targetId) {
44924+
var _a;
44925+
const result = new Set();
44926+
const visited = new Set();
44927+
const queue = [targetId];
44928+
while (queue.length) {
44929+
const currentId = queue.shift();
44930+
if (visited.has(currentId)) {
44931+
continue;
44932+
}
44933+
visited.add(currentId);
44934+
const current = fn.body.blocks.get(currentId);
44935+
for (const pred of current.preds) {
44936+
const predPostDominator = (_a = postDominators.get(pred)) !== null && _a !== void 0 ? _a : pred;
44937+
if (predPostDominator === targetId || result.has(predPostDominator)) {
44938+
result.add(pred);
44939+
}
44940+
queue.push(pred);
44941+
}
44942+
}
44943+
return result;
44944+
}
44945+
4486744946
class StableSidemap {
4486844947
constructor(env) {
4486944948
this.map = new Map();
@@ -44939,42 +45018,7 @@ function inferReactivePlaces(fn) {
4493945018
const place = param.kind === 'Identifier' ? param : param.place;
4494045019
reactiveIdentifiers.markReactive(place);
4494145020
}
44942-
const postDominators = computePostDominatorTree(fn, {
44943-
includeThrowsAsExitNode: false,
44944-
});
44945-
const postDominatorFrontierCache = new Map();
44946-
function isReactiveControlledBlock(id) {
44947-
let controlBlocks = postDominatorFrontierCache.get(id);
44948-
if (controlBlocks === undefined) {
44949-
controlBlocks = postDominatorFrontier(fn, postDominators, id);
44950-
postDominatorFrontierCache.set(id, controlBlocks);
44951-
}
44952-
for (const blockId of controlBlocks) {
44953-
const controlBlock = fn.body.blocks.get(blockId);
44954-
switch (controlBlock.terminal.kind) {
44955-
case 'if':
44956-
case 'branch': {
44957-
if (reactiveIdentifiers.isReactive(controlBlock.terminal.test)) {
44958-
return true;
44959-
}
44960-
break;
44961-
}
44962-
case 'switch': {
44963-
if (reactiveIdentifiers.isReactive(controlBlock.terminal.test)) {
44964-
return true;
44965-
}
44966-
for (const case_ of controlBlock.terminal.cases) {
44967-
if (case_.test !== null &&
44968-
reactiveIdentifiers.isReactive(case_.test)) {
44969-
return true;
44970-
}
44971-
}
44972-
break;
44973-
}
44974-
}
44975-
}
44976-
return false;
44977-
}
45021+
const isReactiveControlledBlock = createControlDominators(fn, place => reactiveIdentifiers.isReactive(place));
4497845022
do {
4497945023
for (const [, block] of fn.body.blocks) {
4498045024
let hasReactiveControl = isReactiveControlledBlock(block.id);
@@ -45092,46 +45136,6 @@ function inferReactivePlaces(fn) {
4509245136
}
4509345137
propagateReactivityToInnerFunctions(fn, true);
4509445138
}
45095-
function postDominatorFrontier(fn, postDominators, targetId) {
45096-
const visited = new Set();
45097-
const frontier = new Set();
45098-
const targetPostDominators = postDominatorsOf(fn, postDominators, targetId);
45099-
for (const blockId of [...targetPostDominators, targetId]) {
45100-
if (visited.has(blockId)) {
45101-
continue;
45102-
}
45103-
visited.add(blockId);
45104-
const block = fn.body.blocks.get(blockId);
45105-
for (const pred of block.preds) {
45106-
if (!targetPostDominators.has(pred)) {
45107-
frontier.add(pred);
45108-
}
45109-
}
45110-
}
45111-
return frontier;
45112-
}
45113-
function postDominatorsOf(fn, postDominators, targetId) {
45114-
var _a;
45115-
const result = new Set();
45116-
const visited = new Set();
45117-
const queue = [targetId];
45118-
while (queue.length) {
45119-
const currentId = queue.shift();
45120-
if (visited.has(currentId)) {
45121-
continue;
45122-
}
45123-
visited.add(currentId);
45124-
const current = fn.body.blocks.get(currentId);
45125-
for (const pred of current.preds) {
45126-
const predPostDominator = (_a = postDominators.get(pred)) !== null && _a !== void 0 ? _a : pred;
45127-
if (predPostDominator === targetId || result.has(predPostDominator)) {
45128-
result.add(pred);
45129-
}
45130-
queue.push(pred);
45131-
}
45132-
}
45133-
return result;
45134-
}
4513545139
class ReactivityMap {
4513645140
constructor(aliasedIdentifiers) {
4513745141
this.hasChanges = false;

compiled/facebook-www/REVISION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
b315a0f7133a3251f72970d56c2ad454bdd47003
1+
d6b1a0573b4c43e5222aee1de5b11a8e4b575c8e
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
b315a0f7133a3251f72970d56c2ad454bdd47003
1+
d6b1a0573b4c43e5222aee1de5b11a8e4b575c8e

compiled/facebook-www/React-dev.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1499,7 +1499,7 @@ __DEV__ &&
14991499
exports.useTransition = function () {
15001500
return resolveDispatcher().useTransition();
15011501
};
1502-
exports.version = "19.3.0-www-classic-b315a0f7-20251117";
1502+
exports.version = "19.3.0-www-classic-d6b1a057-20251117";
15031503
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
15041504
"function" ===
15051505
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-dev.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1499,7 +1499,7 @@ __DEV__ &&
14991499
exports.useTransition = function () {
15001500
return resolveDispatcher().useTransition();
15011501
};
1502-
exports.version = "19.3.0-www-modern-b315a0f7-20251117";
1502+
exports.version = "19.3.0-www-modern-d6b1a057-20251117";
15031503
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
15041504
"function" ===
15051505
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-prod.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,4 +606,4 @@ exports.useSyncExternalStore = function (
606606
exports.useTransition = function () {
607607
return ReactSharedInternals.H.useTransition();
608608
};
609-
exports.version = "19.3.0-www-classic-b315a0f7-20251117";
609+
exports.version = "19.3.0-www-classic-d6b1a057-20251117";

compiled/facebook-www/React-prod.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,4 +606,4 @@ exports.useSyncExternalStore = function (
606606
exports.useTransition = function () {
607607
return ReactSharedInternals.H.useTransition();
608608
};
609-
exports.version = "19.3.0-www-modern-b315a0f7-20251117";
609+
exports.version = "19.3.0-www-modern-d6b1a057-20251117";

compiled/facebook-www/React-profiling.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ exports.useSyncExternalStore = function (
610610
exports.useTransition = function () {
611611
return ReactSharedInternals.H.useTransition();
612612
};
613-
exports.version = "19.3.0-www-classic-b315a0f7-20251117";
613+
exports.version = "19.3.0-www-classic-d6b1a057-20251117";
614614
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
615615
"function" ===
616616
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-profiling.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ exports.useSyncExternalStore = function (
610610
exports.useTransition = function () {
611611
return ReactSharedInternals.H.useTransition();
612612
};
613-
exports.version = "19.3.0-www-modern-b315a0f7-20251117";
613+
exports.version = "19.3.0-www-modern-d6b1a057-20251117";
614614
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
615615
"function" ===
616616
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/ReactART-dev.classic.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20466,10 +20466,10 @@ __DEV__ &&
2046620466
(function () {
2046720467
var internals = {
2046820468
bundleType: 1,
20469-
version: "19.3.0-www-classic-b315a0f7-20251117",
20469+
version: "19.3.0-www-classic-d6b1a057-20251117",
2047020470
rendererPackageName: "react-art",
2047120471
currentDispatcherRef: ReactSharedInternals,
20472-
reconcilerVersion: "19.3.0-www-classic-b315a0f7-20251117"
20472+
reconcilerVersion: "19.3.0-www-classic-d6b1a057-20251117"
2047320473
};
2047420474
internals.overrideHookState = overrideHookState;
2047520475
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
@@ -20504,7 +20504,7 @@ __DEV__ &&
2050420504
exports.Shape = Shape;
2050520505
exports.Surface = Surface;
2050620506
exports.Text = Text;
20507-
exports.version = "19.3.0-www-classic-b315a0f7-20251117";
20507+
exports.version = "19.3.0-www-classic-d6b1a057-20251117";
2050820508
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
2050920509
"function" ===
2051020510
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

0 commit comments

Comments
 (0)