Skip to content

[Web] Add way to ESLint Emscripten libraries #106607

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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

adamscott
Copy link
Member

@adamscott adamscott commented May 19, 2025

Important

This PR adds a package.json file to the root. Don't worry. It is only required by pre-commit (which will run the package.json file in its own custom environment inside the root dir, but no Node/npm is needed), so no npm i required to build Godot and contribute.

Note

This is my first step to modernize the Web stack. Having package.json and eslint.config.mts at the root are needed to properly have access to tools for files through out the whole project. Especiallly since the Web files are disseminated throughout the whole project, and aren't contained entirely in platform/web. (I'm trying my best to not spread out as much as possible, though.) In another PR, I will remove the existing package.json in platform/web.

Note

This PR is neither a bug nor an enhancement. It will be required to upgrade emscripten especially regarding WebXR (cc. @dsnopek). And it will be required to "revert" #105833 (see #105833 (comment)).

This PR replaces the current way we call ESLint in pre-commit. Instead of calling eslint directly, it runs node misc/scripts/run_eslint.mjs in order to preprocess some emscripten library files.

It fixes a huge issue, the fact that it was impossible to lint emscripten libraries with macros.

This is quite "simple". Imagine that you have platform/web/js/libs/library_godot_with_macros.js.
To make it lintable with eslint, you just have now to add platform/web/js/libs/library_godot_with_macros.lint_settings.json with all the macros in the file defined to a value. The file will be preprocessed to remove the macros according to the settings file values and eslint will parse the preprocessed file afterwards.

You have branching macro paths? No problem. The system in my PR supports multiple lint_settings.json files. library_godot_with_macros.lint_settings.webgl_enabled.json and library_godot_with_macros.lint_settings.webgl_disabled.json are valid setting files for library_godot_with_macros.js.

Demo

platform/web/js/libs/library_godot_with_macros.js

function my_test() {
#if HELLO
  console.log("hello");
#elif WORLD
  console.log("world");
#else
  HUH
#endif 
}

platform/web/js/libs/library_godot_with_macros.lint_settings.hello.json

{
  "HELLO": 1,
  "WORLD": 0
}

platform/web/js/libs/library_godot_with_macros.lint_settings.world.json

{
  "HELLO": 0,
  "WORLD": 1
}

platform/web/js/libs/library_godot_with_macros.lint_settings.huh.json

{
  "HELLO": 0,
  "WORLD": 0
}

eslint will complain because of the unindentified symbol HUH.

Conclusion

I cannot stress enough about how much I tried to wrap the problem. I thought initially to just use a ESLint preprocessor in order to strip the macros before linting, but this is quite a naive approach. If variables are defined and used only in some contexts, or if a function is closed early, then ESLint breaks.

This method is not perfect, as it will require multiple lint_settings.json files to properly lint a complex library file with multiple macros used, but it's better than nothing. Emscripten itself doesn't seem to know how to handle their own macros. It leads to obvious syntax errors getting through. They are thinking for a way to fix that issue, though.

@adamscott

This comment has been minimized.

@adamscott adamscott force-pushed the eslint-emscripten-libraries branch from e11bb8f to 0db8934 Compare May 19, 2025 20:11
@dsnopek
Copy link
Contributor

dsnopek commented May 20, 2025

The overall approach makes sense to me and it seems potentially less fragile than trying to preprocess the JS ourselves.

The one thing I'd worry about is that this is loading JS functions directly from within Emscripten to do the preprocessing, and we don't have any guarantee that Emscripten isn't going to change these in an incompatible way. That said, this isn't the first time we've had to do similar things with Emscripten, because they don't always make public, stable APIs for all the things we need.

@AThousandShips AThousandShips added this to the 4.x milestone May 20, 2025
@adamscott adamscott marked this pull request as draft May 22, 2025 18:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants