Skip to content

path.evaluate() ignores shadowed binding for Math methods in MemberExpression #17698

@wulu007

Description

@wulu007

💻

  • Would you like to work on a fix?

How are you using Babel?

Programmatic API (babel.transform, babel.parse)

Input code

function a(Math) {
  var b = Math.ceil(580.82);
}

Configuration file name

No response

Configuration

No response

Current and expected behavior

I am writing a Babel plugin and using path.evaluate() to statically evaluate expressions. I noticed that path.evaluate() fails to check for local bindings when processing CallExpression that involves a MemberExpression (e.g., Math.abs()).

If I shadow the global Math object locally, evaluate() still acts as if it is using the global Math object.

Reproduction Steps (in plugin visitor):

visitor: {
  CallExpression(path) {
    // When visiting `Math.abs(-1)` in the input code
    const result = path.evaluate();
    console.log(result);
  }
}

Current Behavior:
It returns { confident: true, value: 1 }. It ignores the local const Math declaration.

Expected Behavior:
It should return { confident: false } (or evaluate the local function if supported), because Math refers to the local variable, not the global built-in.

Environment

System:

OS: Windows 11 10.0.26100

Binaries:

Node: 22.18.0
Yarn: 1.22.22
npm: 10.9.3
pnpm: 10.27.0

npmPackages:

eslint: catalog: => 9.39.2

Possible solution

The issue seems to be in packages/babel-traverse/src/path/evaluation.ts.

In the _evaluate function, specifically within the if (path.isCallExpression()) block. When handling Identifier callees (like Number(1)), there is a check for !path.scope.getBinding(callee.node.name).

However, inside the if (callee.isMemberExpression()) block (which handles Math.xxx), this check is missing.

Proposed fix:
Add a binding check for the object identifier.

// packages/babel-traverse/src/path/evaluation.ts

if (callee.isMemberExpression()) {
  const object = callee.get("object");
  const property = callee.get("property");

  if (
    object.isIdentifier() &&
    property.isIdentifier() &&
    !path.scope.getBinding(object.node.name) && // <--- ADD THIS CHECK
    isValidObjectCallee(object.node.name) &&
    !isInvalidMethod(property.node.name)
  ) {
     // ...
  }
}

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions