Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: module expression scope handling #16037

Open
1 task done
DMartens opened this issue Oct 12, 2023 · 3 comments 路 May be fixed by #16091
Open
1 task done

[Bug]: module expression scope handling #16037

DMartens opened this issue Oct 12, 2023 · 3 comments 路 May be fixed by #16091

Comments

@DMartens
Copy link

DMartens commented Oct 12, 2023

馃捇

  • Would you like to work on a fix?

How are you using Babel?

@babel/eslint-parser

Input code

Code:

const mod = module {}

Programmatic access:

import { parseForESLint } from '@babel/eslint-parser'
parseForESLint(code, { plugins: ["@babel/proposal-syntax-module-blocks"] })

Configuration file name

babel.config.js

Configuration

{
	"plugins": ["@babel/proposal-syntax-module-blocks"]
}

Current and expected behavior

Currently parsing any code module expression and analyzing the scope will lead to an error:

AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:

  assert(this.__currentScope === null)

    at ScopeManager.__nestScope (project/node_modules/.pnpm/[email protected]/node_modules/eslint-scope/lib/scope-manager.js:193:13)
    at ScopeManager.__nestGlobalScope (project/node_modules/.pnpm/[email protected]/node_modules/eslint-scope/lib/scope-manager.js:201:21)
    at Referencer.Program (project/node_modules/.pnpm/[email protected]/node_modules/eslint-scope/lib/referencer.js:412:27)
    at Referencer.Visitor.visit (project/node_modules/.pnpm/[email protected]/node_modules/esrecurse/esrecurse.js:104:34)
    at Referencer.Visitor.visitChildren (project/node_modules/.pnpm/[email protected]/node_modules/esrecurse/esrecurse.js:88:26)
    at Referencer.Visitor.visit (project/node_modules/.pnpm/[email protected]/node_modules/esrecurse/esrecurse.js:107:14)
    at Referencer.VariableDeclaration (project/node_modules/.pnpm/[email protected]/node_modules/eslint-scope/lib/referencer.js:536:22)
    at Referencer.Visitor.visit (project/node_modules/.pnpm/[email protected]/node_modules/esrecurse/esrecurse.js:104:34)
    at Referencer.Visitor.visitChildren (project/node_modules/.pnpm/[email protected]/node_modules/esrecurse/esrecurse.js:83:38)
    at Referencer.Program (project/node_modules/.pnpm/[email protected]/node_modules/eslint-scope/lib/referencer.js:429:14)

This is triggered here in eslint-scope

The expectation is that no error is thrown.

Environment

  • Babel: 7.23.0
  • Node: 20.8.0
  • npm: 10.2.0
  • OS: Linux
  • Monorepo: no

Possible solution

The problem is that for module expressions Program nodes are generated which are already handled in eslint-scope .
The default visitor creates a global scope and expects no other scope to have been created but this then fails for the scope generated for module expressions.
As such the node must be handled explicitly in the referencer.
Either:

  • keep using a Program node but not adding a global scope for module expressions in the referencer
  • use a ModuleBlock node according to ESTree and add a visitor to the referencer

Additional context

I saw PR #15240 but this change also keeps creating Program nodes.
If this bug report is approved would you prefer creating a ModuleScope or a new kind of scope for module expressions?

@babel-bot
Copy link
Collaborator

Hey @DMartens! We really appreciate you taking the time to report an issue. The collaborators on this project attempt to help as many people as possible, but we're a limited number of volunteers, so it's possible this won't be addressed swiftly.

If you need any help, or just have general Babel or JavaScript questions, we have a vibrant Slack community that typically always has someone willing to help. You can sign-up here for an invite.

@DMartens
Copy link
Author

DMartens commented Nov 7, 2023

Is there anything unclear with the bug report?
To summarize, the parser creates Program nodes for the bodies of the ModuleExpression which eslint-scope only expects once.
I successfully tried locally updating the Program visitor for eslint-scope by using a flag to check whether there was already a program node and if there was, nest an ModuleScope instead.
So no code changes are required for the parser if this is a concern.

@JLHwung
Copy link
Contributor

JLHwung commented Nov 7, 2023

Note that the eslint-scope only supports stage-4 proposals. So it will throw on module expressions.

In @babel/eslint-parser we patch the eslint-scope for the Babel AST: https://github.com/babel/babel/blob/main/eslint/babel-eslint-parser/src/analyze-scope.cjs

feel free to do the same for module expressions.

As for the AST design, the @babel/eslint-parser's policy is to follow ESTree after eslint has implemented it, otherwise use Babel AST instead. So the analyze-scope.cjs should handle the nested Program node. We can create a ModuleScope like you said.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants