Skip to content

[FS] Only generate FS_<symbol> library aliases for functions - #28101

Merged
sbc100 merged 1 commit into
emscripten-core:mainfrom
sbc100:fs-alias-functions
Oct 29, 2026
Merged

sbc100 merged 1 commit into
emscripten-core:mainfrom
sbc100:fs-alias-functions

Conversation

@sbc100

@sbc100 sbc100 commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

In #24116, a loop was added at the end of src/lib/libfs.js to generate $FS_<symbol> wrapper functions ((...args) => FS.foo(...)) for FS API methods. While the comment noted that non-functions should be skipped, the condition only checked key[0] !== key[0].toLowerCase() (which filters out uppercase classes like ErrnoError, FSStream, and FSNode), assuming all lowercase properties on LibraryFS.$FS were functions.

In practice, LibraryFS.$FS also contains lowercase state and object properties (root, mounts, devices, streams, nextInode, nameTable, currentPath, initialized, ignorePermissions, syncFSRequests, and chrdev_stream_ops). Wrapping these in (...args) => FS.<key>(...args) is broken:

  • Calling any of these generated aliases at runtime would unconditionally throw TypeError: FS.<key> is not a function.
  • When compiling with -sINCLUDE_FULL_LIBRARY and --closure=1 (such as with -sEXPORT_ES6), Closure Compiler rejects calls to these non-callable properties on FS.
  • In unoptimized (-O0 / ASSERTIONS) builds, these bogus symbols pollute missingLibrarySymbols, unnecessarily increasing JS code size.

Check typeof LibraryFS.$FS[key] !== 'function' alongside the existing lowercase check so that only actual methods on FS receive function aliases.

Split out from #27747

In emscripten-core#24116, a loop was added at the end of `src/lib/libfs.js` to
generate `$FS_<symbol>` wrapper functions (`(...args) => FS.foo(...)`)
for `FS` API methods. While the comment noted that non-functions should
be skipped, the condition only checked `key[0] !== key[0].toLowerCase()`
(which filters out uppercase classes like `ErrnoError`, `FSStream`, and
`FSNode`), assuming all lowercase properties on `LibraryFS.$FS` were
functions.

In practice, `LibraryFS.$FS` also contains lowercase state and object
properties (`root`, `mounts`, `devices`, `streams`, `nextInode`,
`nameTable`, `currentPath`, `initialized`, `ignorePermissions`,
`syncFSRequests`, and `chrdev_stream_ops`). Wrapping these in
`(...args) => FS.<key>(...args)` is broken:

- Calling any of these generated aliases at runtime would unconditionally
  throw `TypeError: FS.<key> is not a function`.
- When compiling with `-sINCLUDE_FULL_LIBRARY` and `--closure=1` (such
  as with `-sEXPORT_ES6`), Closure Compiler rejects calls to these
  non-callable properties on `FS`.
- In unoptimized (`-O0` / `ASSERTIONS`) builds, these bogus symbols
  pollute `missingLibrarySymbols`, unnecessarily increasing JS code
  size.

Check `typeof LibraryFS.$FS[key] !== 'function'` alongside the existing
lowercase check so that only actual methods on `FS` receive function
aliases.

See: emscripten-core#27747
@sbc100
sbc100 requested a review from kripken October 29, 2026 17:50

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates src/lib/libfs.js to prevent creating aliases for non-function properties of LibraryFS.$FS by verifying that the property is a function. This optimization reduces the overall code size, which is reflected in the updated code size test files and expectations. There are no review comments, so I have no feedback to provide.

@sbc100
sbc100 merged commit 878cc3d into emscripten-core:main Oct 29, 2026
42 checks passed
@sbc100
sbc100 deleted the fs-alias-functions branch October 29, 2026 22:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants