From 0e605ae26e70fc2efdef31178c77d676c8625f28 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 7 Jan 2026 19:53:26 +0000 Subject: [PATCH 1/2] Fix named JS classes in libraries. When a JS library contains a named class, the previous logic blindly prepended the mangled name, resulting in invalid syntax like 'class MyClass MyClass'. This change detects if a class name is already present (excluding 'extends') and replaces it correctly. Fixes #25840 --- src/Fetch.js | 3 +-- src/jsifier.mjs | 2 +- test/test_jslib.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/Fetch.js b/src/Fetch.js index 52619b454e936..40897bd7b996d 100644 --- a/src/Fetch.js +++ b/src/Fetch.js @@ -10,8 +10,7 @@ * This implementation is specifically tailored to only handle 'arraybuffer' * responses. */ -// TODO Use a regular class name when #5840 is fixed. -var FetchXHR = class { +class FetchXHR { // --- Public XHR Properties --- // Event Handlers diff --git a/src/jsifier.mjs b/src/jsifier.mjs index 0d9f9aeddffa6..c28d81aae16f2 100644 --- a/src/jsifier.mjs +++ b/src/jsifier.mjs @@ -717,7 +717,7 @@ function(${args}) { contentText = `var ${mangled} = ` + contentText + ';'; } else if (contentText.startsWith('class ')) { // Handle class declarations (which also have typeof == 'function'.) - contentText = contentText.replace(/^class /, `class ${mangled} `); + contentText = contentText.replace(/^class(?:\s+(?!extends\b)[^{\s]+)?/, `class ${mangled}`); } else { // Handle regular (non-arrow) functions contentText = contentText.replace(/function(?:\s+([^(]+))?\s*\(/, `function ${mangled}(`); diff --git a/test/test_jslib.py b/test/test_jslib.py index a2d8b063c9bb8..7c07d975151ab 100644 --- a/test/test_jslib.py +++ b/test/test_jslib.py @@ -719,3 +719,31 @@ def test_jslib_version_check(self): #endif ''') self.assert_fail([EMCC, '--js-library=libfoo.js'], 'error: libfoo.js:3: #error "library does not support emscripten > 3.0.0"') + + def test_jslib_named_class(self): + create_file('lib.js', r''' + class MyClass { + constructor() { this.x = 42; } + } + + addToLibrary({ + $MyClass: MyClass, + log_class__deps: ['$MyClass'], + log_class: () => { + var i = new MyClass(); + out('MyClass: ' + i.x); + } + }); + ''') + create_file('src.c', r''' + #include + #include + + extern void log_class(); + + int main() { + log_class(); + return 0; + } + ''') + self.do_runf('src.c', 'MyClass: 42', cflags=['--js-library', 'lib.js']) From 7f8e22a37f92d1bf35ebdb83031267ae806b6794 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Thu, 8 Jan 2026 01:29:13 +0000 Subject: [PATCH 2/2] comment --- test/test_jslib.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/test_jslib.py b/test/test_jslib.py index 7c07d975151ab..266408a824eb3 100644 --- a/test/test_jslib.py +++ b/test/test_jslib.py @@ -722,12 +722,13 @@ def test_jslib_version_check(self): def test_jslib_named_class(self): create_file('lib.js', r''' - class MyClass { - constructor() { this.x = 42; } - } - + class ParentClass {} addToLibrary({ - $MyClass: MyClass, + $ParentClass: ParentClass, + $MyClass__deps: ['$ParentClass'], + $MyClass: class extends ParentClass { + constructor() { super(); this.x = 42; } + }, log_class__deps: ['$MyClass'], log_class: () => { var i = new MyClass();