Version
emcc 6.0.9 (4e42238). 5.0.7 is clean with the same commands. Swapping google-closure-compiler between the two shows both halves are needed: 6.0.9's output with 5.0.7's Closure 20240317 is clean, and 5.0.7's output with 6.0.9's Closure 20260726 is clean too.
Repro
// a.cpp
#include <cstdio>
int main() { FILE* f = fopen("/tmp/x.txt", "w"); if (f) { fputs("x", f); fclose(f); } return 0; }
em++ a.cpp -O2 -sEXPORT_ES6=1 --closure=1 -Wall -o a.mjs
building:WARNING: /tmp/emscripten_temp_bm3tsqfu/a.jso1.js:249:46: WARNING - [JSC_WRONG_ARGUMENT_COUNT] Function FS.init: called with 0 argument(s). Function requires at least 3 argument(s) and no more than 3 argument(s).
249| if (!Module["noFSInit"] && !FS.initialized) FS.init();
14 JSC_WRONG_ARGUMENT_COUNT and 4 JSC_TYPE_MISMATCH warnings in total, all in emscripten's own runtime: FS.init, FS.chmod, FS.stat, FS.mkdev, FS.createDevice, FS.write, SYSCALLS.calculateAt. A larger link (our --bind module, which uses NODEFS and SOCKFS) adds FS.createNode, FS.mkdir, NODEFS.createNode, NODEFS.stream_ops.write and SOCKFS.websocket_sock_ops.createPeer: 52 arity warnings, 60 in all.
Without -sEXPORT_ES6 (including -sMODULARIZE=1 alone, or -sINCLUDE_FULL_LIBRARY) there are no warnings, which is presumably why test_closure_full_js_library does not see this. The closure diagnostic is off by default, so a plain -Werror link is unaffected; with -Wall -Werror, which a C++ project's compile flags typically carry into the link, it becomes
em++: error: closure compiler produced warnings and -W=error=closure enabled
Cause
The functions declare parameters that are optional in practice as plain ES6 method parameters with no default and no = in a @param, and are then called with fewer arguments from the same libraries, e.g. init(input, output, error) in libfs.js vs the FS.init() in its addAtInit, stat(path, dontFollow) vs FS.stat(path), calculateAt(dirfd, path, allowEmpty) in libsyscall.js vs 13 of its 15 calls passing two arguments. Two cases go the other way: libsyscall.js passes three arguments to mkdir(path, mode = 0o777), and libnodefs.js passes six to its five-parameter stream_ops.write. The calls come from libfs.js, libnodefs.js, libnoderawfs.js, libsockfs.js and libsyscall.js.
The JSC_TYPE_MISMATCH warnings have a separate cause: libfs.js declares nameTable: null (L57) and only assigns new Array(4096) in staticInit (L1578), so Closure types the field as null and objects to every FS.nameTable[hash] access and to Object.entries(FS.nameTable) in unmount.
Suggested fix
Give the optional parameters defaults, as mkdir(path, mode = 0o777) already does, or annotate them @param {...=} as libfs.js does for createDataFile's data; drop the surplus arguments at the two call sites above; and initialise nameTable to its array (or annotate the field @type {Array}) instead of null. An -sEXPORT_ES6 variant of test_closure_full_js_library would keep it from coming back.
Version
emcc 6.0.9 (4e42238). 5.0.7 is clean with the same commands. Swapping
google-closure-compilerbetween the two shows both halves are needed: 6.0.9's output with 5.0.7's Closure 20240317 is clean, and 5.0.7's output with 6.0.9's Closure 20260726 is clean too.Repro
14
JSC_WRONG_ARGUMENT_COUNTand 4JSC_TYPE_MISMATCHwarnings in total, all in emscripten's own runtime:FS.init,FS.chmod,FS.stat,FS.mkdev,FS.createDevice,FS.write,SYSCALLS.calculateAt. A larger link (our--bindmodule, which uses NODEFS and SOCKFS) addsFS.createNode,FS.mkdir,NODEFS.createNode,NODEFS.stream_ops.writeandSOCKFS.websocket_sock_ops.createPeer: 52 arity warnings, 60 in all.Without
-sEXPORT_ES6(including-sMODULARIZE=1alone, or-sINCLUDE_FULL_LIBRARY) there are no warnings, which is presumably whytest_closure_full_js_librarydoes not see this. Theclosurediagnostic is off by default, so a plain-Werrorlink is unaffected; with-Wall -Werror, which a C++ project's compile flags typically carry into the link, it becomesCause
The functions declare parameters that are optional in practice as plain ES6 method parameters with no default and no
=in a@param, and are then called with fewer arguments from the same libraries, e.g.init(input, output, error)inlibfs.jsvs theFS.init()in itsaddAtInit,stat(path, dontFollow)vsFS.stat(path),calculateAt(dirfd, path, allowEmpty)inlibsyscall.jsvs 13 of its 15 calls passing two arguments. Two cases go the other way:libsyscall.jspasses three arguments tomkdir(path, mode = 0o777), andlibnodefs.jspasses six to its five-parameterstream_ops.write. The calls come fromlibfs.js,libnodefs.js,libnoderawfs.js,libsockfs.jsandlibsyscall.js.The
JSC_TYPE_MISMATCHwarnings have a separate cause:libfs.jsdeclaresnameTable: null(L57) and only assignsnew Array(4096)instaticInit(L1578), so Closure types the field asnulland objects to everyFS.nameTable[hash]access and toObject.entries(FS.nameTable)inunmount.Suggested fix
Give the optional parameters defaults, as
mkdir(path, mode = 0o777)already does, or annotate them@param {...=}aslibfs.jsdoes forcreateDataFile'sdata; drop the surplus arguments at the two call sites above; and initialisenameTableto its array (or annotate the field@type {Array}) instead ofnull. An-sEXPORT_ES6variant oftest_closure_full_js_librarywould keep it from coming back.