Repository: facebook/react
File: compiler/packages/babel-plugin-react-compiler/src/Inference/InferReferenceEffects.ts (TypeScript)

Code before:
          valueKind: {
            kind: ValueKind.Primitive,
            reason: new Set([ValueReason.Other]),
            context: new Set(),
          },
          effect: {
            kind: Effect.Read,
            reason: ValueReason.Other,
          },
        };
        break;
      }
      case 'ArrayExpression': {
        const valueKind: AbstractValue = hasContextRefOperand(state, instrValue)
          ? {
              kind: ValueKind.Context,
              reason: new Set([ValueReason.Other]),
              context: new Set(),
            }
          : {
              kind: ValueKind.Mutable,
              reason: new Set([ValueReason.Other]),
              context: new Set(),
            };
        continuation = {
          kind: 'initialize',
          valueKind,
          effect: {kind: Effect.Capture, reason: ValueReason.Other},
          lvalueEffect: Effect.Store,
        };
        break;
      }
      case 'NewExpression': {
        /**
         * For new expressions, we infer a `read` effect on the Class / Function type
         * to avoid extending mutable ranges of locally created classes, e.g.
         * ```js
         * const MyClass = getClass();
         * const value = new MyClass(val1, val2)
         *                   ^ (read)   ^ (conditionally mutate)
         * ```
         *
         * Risks:
         * Classes / functions created during render could technically capture and
         * mutate their enclosing scope, which we currently do not detect.
         */
        const valueKind: AbstractValue = {
          kind: ValueKind.Mutable,
          reason: new Set([ValueReason.Other]),
          context: new Set(),
        };

Review comment (bug):
Hmmm it seems wrong to do this only for array and object expressions: there could just as easily be a function call or constructor that captures context values in the same way. I think we missed this when we originally added the context ref check — let's generalize this check

Code after:
          valueKind: {
            kind: ValueKind.Primitive,
            reason: new Set([ValueReason.Other]),
            context: new Set(),
          },
          effect: {
            kind: Effect.Read,
            reason: ValueReason.Other,
          },
        };
        break;
      }
      case 'ArrayExpression': {
        const contextRefOperands = getContextRefOperand(state, instrValue);
        const valueKind: AbstractValue =
          contextRefOperands.length > 0
            ? {
                kind: ValueKind.Context,
                reason: new Set([ValueReason.Other]),
                context: new Set(contextRefOperands),
              }
            : {
                kind: ValueKind.Mutable,
                reason: new Set([ValueReason.Other]),
                context: new Set(),
              };
        continuation = {
          kind: 'initialize',
          valueKind,
          effect: {kind: Effect.Capture, reason: ValueReason.Other},
          lvalueEffect: Effect.Store,
        };
        break;
      }
      case 'NewExpression': {
        /**
         * For new expressions, we infer a `read` effect on the Class / Function type
         * to avoid extending mutable ranges of locally created classes, e.g.
         * ```js
         * const MyClass = getClass();
         * const value = new MyClass(val1, val2)
         *                   ^ (read)   ^ (conditionally mutate)
         * ```
         *
         * Risks:
         * Classes / functions created during render could technically capture and
         * mutate their enclosing scope, which we currently do not detect.
         */
        const valueKind: AbstractValue = {
          kind: ValueKind.Mutable,
          reason: new Set([ValueReason.Other]),