Skip to content

Commit b8dcf8d

Browse files
committed
[compiler][bugfix] Returned functions are not always frozen (#33047)
Fixes an edge case in React Compiler's effects inference model. Returned values should only be typed as 'frozen' if they are (1) local and (2) not a function expression which may capture and mutate this function's outer context. See test fixtures for details --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33047). * #32765 * #32747 * __->__ #33047 DiffTrain build for [12f4cb8](12f4cb8)
1 parent 253209b commit b8dcf8d

35 files changed

+102
-95
lines changed

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

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45941,15 +45941,15 @@ function getWriteErrorReason(abstractValue) {
4594145941
}
4594245942
}
4594345943

45944-
var _InferenceState_values, _InferenceState_variables;
45944+
var _InferenceState_isFunctionExpression, _InferenceState_values, _InferenceState_variables;
4594545945
const UndefinedValue = {
4594645946
kind: 'Primitive',
4594745947
loc: GeneratedSource,
4594845948
value: undefined,
4594945949
};
4595045950
function inferReferenceEffects(fn, options = { isFunctionExpression: false }) {
4595145951
var _a;
45952-
const initialState = InferenceState.empty(fn.env);
45952+
const initialState = InferenceState.empty(fn.env, options.isFunctionExpression);
4595345953
const value = {
4595445954
kind: 'Primitive',
4595545955
loc: fn.loc,
@@ -46070,15 +46070,20 @@ function inferReferenceEffects(fn, options = { isFunctionExpression: false }) {
4607046070
}
4607146071
}
4607246072
class InferenceState {
46073-
constructor(env, values, variables) {
46073+
constructor(env, isFunctionExpression, values, variables) {
46074+
_InferenceState_isFunctionExpression.set(this, void 0);
4607446075
_InferenceState_values.set(this, void 0);
4607546076
_InferenceState_variables.set(this, void 0);
4607646077
this.env = env;
46078+
__classPrivateFieldSet(this, _InferenceState_isFunctionExpression, isFunctionExpression, "f");
4607746079
__classPrivateFieldSet(this, _InferenceState_values, values, "f");
4607846080
__classPrivateFieldSet(this, _InferenceState_variables, variables, "f");
4607946081
}
46080-
static empty(env) {
46081-
return new InferenceState(env, new Map(), new Map());
46082+
static empty(env, isFunctionExpression) {
46083+
return new InferenceState(env, isFunctionExpression, new Map(), new Map());
46084+
}
46085+
get isFunctionExpression() {
46086+
return __classPrivateFieldGet(this, _InferenceState_isFunctionExpression, "f");
4608246087
}
4608346088
initialize(value, kind) {
4608446089
CompilerError.invariant(value.kind !== 'LoadLocal', {
@@ -46332,11 +46337,11 @@ class InferenceState {
4633246337
return null;
4633346338
}
4633446339
else {
46335-
return new InferenceState(this.env, nextValues !== null && nextValues !== void 0 ? nextValues : new Map(__classPrivateFieldGet(this, _InferenceState_values, "f")), nextVariables !== null && nextVariables !== void 0 ? nextVariables : new Map(__classPrivateFieldGet(this, _InferenceState_variables, "f")));
46340+
return new InferenceState(this.env, __classPrivateFieldGet(this, _InferenceState_isFunctionExpression, "f"), nextValues !== null && nextValues !== void 0 ? nextValues : new Map(__classPrivateFieldGet(this, _InferenceState_values, "f")), nextVariables !== null && nextVariables !== void 0 ? nextVariables : new Map(__classPrivateFieldGet(this, _InferenceState_variables, "f")));
4633646341
}
4633746342
}
4633846343
clone() {
46339-
return new InferenceState(this.env, new Map(__classPrivateFieldGet(this, _InferenceState_values, "f")), new Map(__classPrivateFieldGet(this, _InferenceState_variables, "f")));
46344+
return new InferenceState(this.env, __classPrivateFieldGet(this, _InferenceState_isFunctionExpression, "f"), new Map(__classPrivateFieldGet(this, _InferenceState_values, "f")), new Map(__classPrivateFieldGet(this, _InferenceState_variables, "f")));
4634046345
}
4634146346
debug() {
4634246347
const result = { values: {}, variables: {} };
@@ -46373,7 +46378,7 @@ class InferenceState {
4637346378
}
4637446379
}
4637546380
}
46376-
_InferenceState_values = new WeakMap(), _InferenceState_variables = new WeakMap();
46381+
_InferenceState_isFunctionExpression = new WeakMap(), _InferenceState_values = new WeakMap(), _InferenceState_variables = new WeakMap();
4637746382
function inferParam(param, initialState, paramKind) {
4637846383
let value;
4637946384
let place;
@@ -47064,7 +47069,9 @@ function inferBlock(env, state, block, functionEffects) {
4706447069
let effect;
4706547070
if (block.terminal.kind === 'return' || block.terminal.kind === 'throw') {
4706647071
if (state.isDefined(operand) &&
47067-
state.kind(operand).kind === ValueKind.Context) {
47072+
((operand.identifier.type.kind === 'Function' &&
47073+
state.isFunctionExpression) ||
47074+
state.kind(operand).kind === ValueKind.Context)) {
4706847075
effect = Effect.ConditionallyMutate;
4706947076
}
4707047077
else {

compiled/facebook-www/REVISION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
49ea8bf5698f017022517be79f5f53e6f6a4dad3
1+
12f4cb85c5847758ece81fc95b7eaedc1fb9ebd0
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
49ea8bf5698f017022517be79f5f53e6f6a4dad3
1+
12f4cb85c5847758ece81fc95b7eaedc1fb9ebd0

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1538,7 +1538,7 @@ __DEV__ &&
15381538
exports.useTransition = function () {
15391539
return resolveDispatcher().useTransition();
15401540
};
1541-
exports.version = "19.2.0-www-classic-49ea8bf5-20250430";
1541+
exports.version = "19.2.0-www-classic-12f4cb85-20250430";
15421542
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
15431543
"function" ===
15441544
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
@@ -1538,7 +1538,7 @@ __DEV__ &&
15381538
exports.useTransition = function () {
15391539
return resolveDispatcher().useTransition();
15401540
};
1541-
exports.version = "19.2.0-www-modern-49ea8bf5-20250430";
1541+
exports.version = "19.2.0-www-modern-12f4cb85-20250430";
15421542
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
15431543
"function" ===
15441544
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
@@ -636,4 +636,4 @@ exports.useSyncExternalStore = function (
636636
exports.useTransition = function () {
637637
return ReactSharedInternals.H.useTransition();
638638
};
639-
exports.version = "19.2.0-www-classic-49ea8bf5-20250430";
639+
exports.version = "19.2.0-www-classic-12f4cb85-20250430";

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,4 +636,4 @@ exports.useSyncExternalStore = function (
636636
exports.useTransition = function () {
637637
return ReactSharedInternals.H.useTransition();
638638
};
639-
exports.version = "19.2.0-www-modern-49ea8bf5-20250430";
639+
exports.version = "19.2.0-www-modern-12f4cb85-20250430";

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ exports.useSyncExternalStore = function (
640640
exports.useTransition = function () {
641641
return ReactSharedInternals.H.useTransition();
642642
};
643-
exports.version = "19.2.0-www-classic-49ea8bf5-20250430";
643+
exports.version = "19.2.0-www-classic-12f4cb85-20250430";
644644
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
645645
"function" ===
646646
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
@@ -640,7 +640,7 @@ exports.useSyncExternalStore = function (
640640
exports.useTransition = function () {
641641
return ReactSharedInternals.H.useTransition();
642642
};
643-
exports.version = "19.2.0-www-modern-49ea8bf5-20250430";
643+
exports.version = "19.2.0-www-modern-12f4cb85-20250430";
644644
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
645645
"function" ===
646646
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
@@ -19014,10 +19014,10 @@ __DEV__ &&
1901419014
(function () {
1901519015
var internals = {
1901619016
bundleType: 1,
19017-
version: "19.2.0-www-classic-49ea8bf5-20250430",
19017+
version: "19.2.0-www-classic-12f4cb85-20250430",
1901819018
rendererPackageName: "react-art",
1901919019
currentDispatcherRef: ReactSharedInternals,
19020-
reconcilerVersion: "19.2.0-www-classic-49ea8bf5-20250430"
19020+
reconcilerVersion: "19.2.0-www-classic-12f4cb85-20250430"
1902119021
};
1902219022
internals.overrideHookState = overrideHookState;
1902319023
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
@@ -19051,7 +19051,7 @@ __DEV__ &&
1905119051
exports.Shape = Shape;
1905219052
exports.Surface = Surface;
1905319053
exports.Text = Text;
19054-
exports.version = "19.2.0-www-classic-49ea8bf5-20250430";
19054+
exports.version = "19.2.0-www-classic-12f4cb85-20250430";
1905519055
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
1905619056
"function" ===
1905719057
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

0 commit comments

Comments
 (0)