From 952d880b9bafc941d36d8543f40f1fd83fdc0681 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Fri, 2 Oct 2026 15:59:37 -0700 Subject: [PATCH] [GL] Support cross-library alias targets in recordGLProcAddressGet When `recordGLProcAddressGet` processes `LibraryGLEmulation`, alias targets such as `glGenFramebuffers` live in `LibraryGL` (which has already been merged into `LibraryManager.library`), not in `lib`. Check `LibraryManager.library` in addition to `lib` so that targets like `glGenFramebuffers` in `emscripten_glGenFramebuffersOES` are updated to point to `emscripten_glGenFramebuffers`. See: #27852 --- src/lib/libwebgl.js | 10 +++++++--- test/test_other.py | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/lib/libwebgl.js b/src/lib/libwebgl.js index d90d3b2a9ba18..8523213c5c10f 100644 --- a/src/lib/libwebgl.js +++ b/src/lib/libwebgl.js @@ -4228,10 +4228,14 @@ function recordGLProcAddressGet(lib) { } } // Also update any alias targets to point to the emscripten_-prefixed - // versions. e.g. both the name of the symbol *and* it's target need updating - // in cases such as `glMultiDrawElements: 'glMultiDrawElementsWEBGL'` + // versions. e.g. both the name of the symbol *and* its target need updating + // in cases such as `glMultiDrawElements: 'glMultiDrawElementsWEBGL'`. + // Cross-library targets (such as glGenFramebuffers in LibraryGLEmulation) + // are looked up in LibraryManager.library as well. for (const [sym, target] of Object.entries(lib)) { - if (sym.startsWith('emscripten_gl') && typeof target === 'string' && lib.hasOwnProperty('emscripten_' + target)) { + if (sym.startsWith('emscripten_gl') && typeof target === 'string' && + (lib.hasOwnProperty('emscripten_' + target) || + LibraryManager.library.hasOwnProperty('emscripten_' + target))) { lib[sym] = 'emscripten_' + target; } } diff --git a/test/test_other.py b/test/test_other.py index 21e718438b0f8..7ec77def5b0de 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -2543,6 +2543,32 @@ def test_dylink_webgl_alias(self): '-Wno-experimental', ]) + def test_dylink_glemu_alias(self): + # In libglemu.js, `glGenFramebuffersOES` is an alias for `glGenFramebuffers` (defined + # in libwebgl.js). `recordGLProcAddressGet` renames both to `emscripten_gl*` so that + # `glGenFramebuffersOES` -> `emscripten_glGenFramebuffersOES` -> `emscripten_glGenFramebuffers`. + # If the cross-library target of `emscripten_glGenFramebuffersOES` is not updated to + # `emscripten_glGenFramebuffers` and `glGenFramebuffers` is exported from Wasm, jsifier + # mistakes `emscripten_glGenFramebuffersOES` for a native alias and fails to define it + # in JS before `_glGenFramebuffersOES = _emscripten_glGenFramebuffersOES` is evaluated. + create_file('test.c', r''' +#define GL_GLEXT_PROTOTYPES 1 +#include +#include +#include + +// Export a native `glGenFramebuffers` from Wasm (simulating the native GL wrappers in +// libgl when exported via MAIN_MODULE or EXPORT_ALL) so that an un-prefixed alias target +// of `'glGenFramebuffers'` would be treated by jsifier as a native Wasm export. +__attribute__((used)) void glGenFramebuffers(GLsizei n, GLuint* ids) {} + +int main() { + printf("glGenFramebuffersOES: %p\n", &glGenFramebuffersOES); + printf("done\n"); + return 0; +}''') + self.do_runf('test.c', 'done\n', cflags=['-sMAIN_MODULE=2', '-sLEGACY_GL_EMULATION']) + def test_dylink_library_search(self): # Test library resolution in the case when both static and dynamic library are present. create_file('side_dyn.c', r'''