Skip to content

Conversation

@poteto
Copy link
Member

@poteto poteto commented Aug 4, 2025

When processing nested method calls like Math.floor(diff.bar()), the compiler would trigger an invariant that MethodCall::property must be a MemberExpression but got an Identifier.

The issue occurred when the property (e.g., Math.floor) was memoized in a reactive scope and promoted to a named identifier. Later during codegen, retrieving this memoized temporary would return just an Identifier instead of the expected MemberExpression.

The fix handles this case by checking if the property has been memoized as an Identifier and using it directly for the call expression, rather than requiring it to be a MemberExpression.

This fixes two test cases that were previously failing.

@meta-cla meta-cla bot added the CLA Signed label Aug 4, 2025
@github-actions github-actions bot added the React Core Team Opened by a member of the React Core Team label Aug 4, 2025
const items = makeArray(0, 1, 2, null, 4, false, 6);
t1 = Math;
t2 = t1.max;
t3 = 2;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this cache slot seems unnecessary

Copy link
Member

@josephsavona josephsavona left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this! See comments just to make sure this is sound

Comment on lines +1831 to +1840
// Reconstruct the MemberExpression if we previously saw an Identifier.
if (memberExpr.type === 'Identifier') {
const args = instrValue.args.map(arg => codegenArgument(cx, arg));
value = createCallExpression(
cx.env,
memberExpr,
args,
instrValue.loc,
isHook,
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, the invariant was there to make sure that we don't rewrite a method invocation, which may read from its receiver. In the Math.* cases they are static functions and that isn't a problem, but i'm wondering if the wrong signature could break compilation w the change as implemented.

I think it would be something that a) has the receiver as readonly and b) returns a primitive. Can you try constructing a method like this in shared-runtime and type it (shared-runtime-type-provider) to check that it works correctly?

poteto added a commit that referenced this pull request Aug 4, 2025
We received some bug reports about invariants reported by the compiler
in their codebase. Adding them as repros.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34099).
* #34100
* __->__ #34099
@poteto poteto force-pushed the pr34100 branch 2 times, most recently from f6affef to d6b8537 Compare August 7, 2025 15:44
When processing nested method calls like `Math.floor(diff.bar())`, the compiler would trigger an invariant that `MethodCall::property must be a MemberExpression but got an Identifier`.

The issue occurred when the property (e.g., Math.floor) was memoized in a reactive scope and promoted to a named identifier. Later during codegen, retrieving this memoized temporary would return just an Identifier instead of the expected MemberExpression.

The fix handles this case by checking if the property has been memoized as an Identifier and using it directly for the call expression, rather than requiring it to be a MemberExpression.

This fixes two test cases that were previously failing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed React Core Team Opened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants