Skip to content

Commit b8f54f8

Browse files
authored
Allow EXPORTED_FUNCTIONS to include and export JS library symbols (#21867)
Prior to this change one would need to add JS library symbols to both `DEFAULT_LIBRARY_FUNCS_TO_INCLUDE` and `EXPORTED_FUNCTIONS` to achieve this (confusingly with different name mangling for each).
1 parent 16fd432 commit b8f54f8

File tree

6 files changed

+49
-29
lines changed

6 files changed

+49
-29
lines changed

ChangeLog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ See docs/process.md for more on how version tagging works.
2020

2121
3.1.60 (in development)
2222
-----------------------
23+
- The `EXPORTED_FUNCTIONS` list can now include JS library symbols even if they
24+
have not been otherwise included (e.g. via `DEFAULT_LIBRARY_FUNCS_TO_INCLUDE`).
25+
(#21867)
2326

2427
3.1.59 - 04/30/24
2528
-----------------

site/source/docs/tools_reference/settings_reference.rst

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -956,8 +956,7 @@ EXPORT_EXCEPTION_HANDLING_HELPERS
956956
=================================
957957

958958
Make the exception message printing function, 'getExceptionMessage' available
959-
in the JS library for use, by adding necessary symbols to EXPORTED_FUNCTIONS
960-
and DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.
959+
in the JS library for use, by adding necessary symbols to EXPORTED_FUNCTIONS.
961960

962961
This works with both Emscripten EH and Wasm EH. When you catch an exception
963962
from JS, that gives you a user-thrown value in case of Emscripten EH, and a
@@ -1313,15 +1312,17 @@ to load ok, but we do actually recompile).
13131312
EXPORTED_FUNCTIONS
13141313
==================
13151314

1316-
Functions that are explicitly exported. These functions are kept alive
1317-
through LLVM dead code elimination, and also made accessible outside of the
1318-
generated code even after running closure compiler (on "Module"). The
1315+
Symbols that are explicitly exported. These symbols are kept alive through
1316+
LLVM dead code elimination, and also made accessible outside of the
1317+
generated code even after running closure compiler (on "Module"). Native
13191318
symbols listed here require an ``_`` prefix.
13201319

13211320
By default if this setting is not specified on the command line the
13221321
``_main`` function will be implicitly exported. In STANDALONE_WASM mode the
13231322
default export is ``__start`` (or ``__initialize`` if --no-entry is specified).
13241323

1324+
JS Library symbols can also be added to this list (without the leading `$`).
1325+
13251326
.. _export_all:
13261327

13271328
EXPORT_ALL
@@ -1358,13 +1359,16 @@ DEFAULT_LIBRARY_FUNCS_TO_INCLUDE
13581359
================================
13591360

13601361
JS library elements (C functions implemented in JS) that we include by
1361-
default. If you want to make sure something is included by the JS compiler,
1362+
default. If you want to make sure something is included by the JS compiler,
13621363
add it here. For example, if you do not use some ``emscripten_*`` C API call
1363-
from C, but you want to call it from JS, add it here (and in EXPORTED
1364-
FUNCTIONS with prefix "_", if you use closure compiler). Note that the name
1365-
may be slightly misleading, as this is for any JS library element, and not
1366-
just functions. For example, you can include the Browser object by adding
1367-
"$Browser" to this list.
1364+
from C, but you want to call it from JS, add it here.
1365+
Note that the name may be slightly misleading, as this is for any JS
1366+
library element, and not just functions. For example, you can include the
1367+
Browser object by adding "$Browser" to this list.
1368+
1369+
If you want to both include and export a JS library symbol, it is enough to
1370+
simply add it to EXPORTED_FUNCTIONS, without also adding it to
1371+
DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.
13681372

13691373
.. _include_full_library:
13701374

src/jsifier.mjs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,10 @@ export function runJSify(symbolsOnly) {
172172
symbolsNeeded.push('$' + sym);
173173
}
174174
}
175-
if (INCLUDE_FULL_LIBRARY) {
176-
for (const key of Object.keys(LibraryManager.library)) {
177-
if (!isDecorator(key)) {
175+
176+
for (const key of Object.keys(LibraryManager.library)) {
177+
if (!isDecorator(key)) {
178+
if (INCLUDE_FULL_LIBRARY || EXPORTED_FUNCTIONS.has(mangleCSymbolName(key))) {
178179
symbolsNeeded.push(key);
179180
}
180181
}

src/settings.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -743,8 +743,7 @@ var EXCEPTION_CATCHING_ALLOWED = [];
743743
var DISABLE_EXCEPTION_THROWING = false;
744744

745745
// Make the exception message printing function, 'getExceptionMessage' available
746-
// in the JS library for use, by adding necessary symbols to EXPORTED_FUNCTIONS
747-
// and DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.
746+
// in the JS library for use, by adding necessary symbols to EXPORTED_FUNCTIONS.
748747
//
749748
// This works with both Emscripten EH and Wasm EH. When you catch an exception
750749
// from JS, that gives you a user-thrown value in case of Emscripten EH, and a
@@ -1042,14 +1041,16 @@ var NODERAWFS = false;
10421041
// [link]
10431042
var NODE_CODE_CACHING = false;
10441043

1045-
// Functions that are explicitly exported. These functions are kept alive
1046-
// through LLVM dead code elimination, and also made accessible outside of the
1047-
// generated code even after running closure compiler (on "Module"). The
1044+
// Symbols that are explicitly exported. These symbols are kept alive through
1045+
// LLVM dead code elimination, and also made accessible outside of the
1046+
// generated code even after running closure compiler (on "Module"). Native
10481047
// symbols listed here require an ``_`` prefix.
10491048
//
10501049
// By default if this setting is not specified on the command line the
10511050
// ``_main`` function will be implicitly exported. In STANDALONE_WASM mode the
10521051
// default export is ``__start`` (or ``__initialize`` if --no-entry is specified).
1052+
//
1053+
// JS Library symbols can also be added to this list (without the leading `$`).
10531054
// [link]
10541055
var EXPORTED_FUNCTIONS = [];
10551056

@@ -1074,13 +1075,16 @@ var EXPORT_KEEPALIVE = true;
10741075
var RETAIN_COMPILER_SETTINGS = false;
10751076

10761077
// JS library elements (C functions implemented in JS) that we include by
1077-
// default. If you want to make sure something is included by the JS compiler,
1078+
// default. If you want to make sure something is included by the JS compiler,
10781079
// add it here. For example, if you do not use some ``emscripten_*`` C API call
1079-
// from C, but you want to call it from JS, add it here (and in EXPORTED
1080-
// FUNCTIONS with prefix "_", if you use closure compiler). Note that the name
1081-
// may be slightly misleading, as this is for any JS library element, and not
1082-
// just functions. For example, you can include the Browser object by adding
1083-
// "$Browser" to this list.
1080+
// from C, but you want to call it from JS, add it here.
1081+
// Note that the name may be slightly misleading, as this is for any JS
1082+
// library element, and not just functions. For example, you can include the
1083+
// Browser object by adding "$Browser" to this list.
1084+
//
1085+
// If you want to both include and export a JS library symbol, it is enough to
1086+
// simply add it to EXPORTED_FUNCTIONS, without also adding it to
1087+
// DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.
10841088
// [link]
10851089
var DEFAULT_LIBRARY_FUNCS_TO_INCLUDE = [];
10861090

test/test_other.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7234,7 +7234,6 @@ def test_dlsym_rtld_default_js_symbol(self):
72347234
self.run_process([EMCC, 'main.c',
72357235
'--js-library=lib.js',
72367236
'-sMAIN_MODULE=2',
7237-
'-sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE=foo,bar',
72387237
'-sEXPORTED_FUNCTIONS=_main,_foo,_bar'])
72397238

72407239
# Fist test the successful use of a JS function with dlsym
@@ -7382,7 +7381,6 @@ def test_emscripten_scan_stack(self):
73827381

73837382
def test_no_warn_exported_jslibfunc(self):
73847383
self.run_process([EMCC, test_file('hello_world.c'),
7385-
'-sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE=alGetError',
73867384
'-sEXPORTED_FUNCTIONS=_main,_alGetError'])
73877385

73887386
# Same again but with `_alGet` wich does not exist. This is a regression
@@ -12411,6 +12409,15 @@ def test_jslib_mangling(self):
1241112409
''')
1241212410
self.run_process([EMCC, test_file('hello_world.c'), '--js-library=lib.js', '-sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE=$__foo'])
1241312411

12412+
def test_jslib_exported_functions(self):
12413+
create_file('lib.js', '''
12414+
addToLibrary({
12415+
$Foo: () => 43,
12416+
});
12417+
''')
12418+
self.run_process([EMCC, test_file('hello_world.c'), '--js-library=lib.js', '-sEXPORTED_FUNCTIONS=Foo,_main'])
12419+
self.assertContained("Module['Foo'] = ", read_file('a.out.js'))
12420+
1241412421
def test_wasm2js_no_dylink(self):
1241512422
for arg in ['-sMAIN_MODULE', '-sSIDE_MODULE', '-sRELOCATABLE']:
1241612423
print(arg)

tools/link.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1792,8 +1792,7 @@ def get_full_import_name(name):
17921792
# JS, you may need to manipulate the refcount manually not to leak memory.
17931793
# What you need to do is different depending on the kind of EH you use
17941794
# (https://github.com/emscripten-core/emscripten/issues/17115).
1795-
settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$getExceptionMessage', '$incrementExceptionRefcount', '$decrementExceptionRefcount']
1796-
settings.EXPORTED_FUNCTIONS += ['getExceptionMessage', '$incrementExceptionRefcount', '$decrementExceptionRefcount']
1795+
settings.EXPORTED_FUNCTIONS += ['getExceptionMessage', 'incrementExceptionRefcount', 'decrementExceptionRefcount']
17971796
if settings.WASM_EXCEPTIONS:
17981797
settings.REQUIRED_EXPORTS += ['__cpp_exception']
17991798

@@ -3103,6 +3102,8 @@ def add_js_deps(sym):
31033102
add_js_deps(sym)
31043103
for sym in settings.EXPORTED_RUNTIME_METHODS:
31053104
add_js_deps(shared.demangle_c_symbol_name(sym))
3105+
for sym in settings.EXPORTED_FUNCTIONS:
3106+
add_js_deps(shared.demangle_c_symbol_name(sym))
31063107
if settings.ASYNCIFY:
31073108
settings.ASYNCIFY_IMPORTS_EXCEPT_JS_LIBS = settings.ASYNCIFY_IMPORTS[:]
31083109
settings.ASYNCIFY_IMPORTS += ['*.' + x for x in js_info['asyncFuncs']]

0 commit comments

Comments
 (0)