crossbind
GitHub
GUIDE · CONCEPTS · FILESYSTEM

Filesystem

C++ wants paths. What a path means depends on where the module runs: real disk in Node, an origin-private store or plain memory in the browser, per-invocation memory on the edge. This page maps every combination, including how a file from an <input> element becomes a path your C++ can open.

The two browser roots

MountBacked bySurvives a reloadAvailable when
/opfs/<app>/the Origin Private File SystemyesuseWorker: true, fs.opfs not disabled, browser support
/memfs/<app>/in-memoryno - tab session onlyalways

<app> is general.name from cppjs.config.js. OPFS is a Worker-scope-only API, which is the single most important consequence on this page:

OPFS requires useWorker: true
Mounting /opfs/... from the main thread throws. If the browser has no OPFS support - or the backend is blocked - the path is redirected to /memfs/ and the reason is logged, so writes keep working but stop persisting.
src/main.js
const m = await initNative({
useWorker: true, "color:#78829a">// mandatory for OPFS
fs: { opfs: true }, "color:#78829a">// the browser default, shown for clarity
});
 
"color:#78829a">// Anything under /opfs/<app>/ is still there after a reload.
m.FS.writeFile('/opfs/myapp/data.bin', new Uint8Array([1, 2, 3]));

Module helpers

HelperDoes
m.FSthe standard virtual filesystem: mkdirTree, writeFile, readFile, …
m.getDefaultPath()returns /opfs or /memfs for the current configuration
m.getFinalPath(path)validates a path, falling back when OPFS is unavailable
m.getRandomPath(startPath?)creates <start>/<app>/automounted/<random> and returns it
m.autoMountFiles(files, parentPath?)streams File[] into the filesystem, returns the mounted paths
m.getFileBytes(path)file contents as a Uint8Array
m.getFileList(startPath?)recursive listing as [{ path, size }]
JavaScript
m.FS.mkdirTree('/memfs/myapp/cache');
m.FS.writeFile('/memfs/myapp/cache/data.bin', new Uint8Array([1, 2, 3]));
const bytes = m.FS.readFile('/memfs/myapp/cache/data.bin');
m.FS exists only after init
Await the initNative(...) promise (or use the onRuntimeInitialized hook) before touching it.

Files the user picked

A File from an <input type=file> never has a path your C++ can open. autoMountFiles streams it in and hands back paths that do - no size limit beyond storage, so multi-gigabyte inputs are fine.

src/main.js
const input = document.querySelector('input[type=file]');
 
input.addEventListener('change', async () => {
const paths = await m.autoMountFiles(Array.from(input.files));
"color:#78829a">// e.g. ['/opfs/myapp/automounted/123456/photo.jpg']
for (const path of paths) {
m.processImage(path);
}
});

Pass a second argument to mount into a known directory instead of a random one: await m.autoMountFiles(files, '/opfs/myapp/uploads').

Getting results back to JavaScript

C++ writes to a path; JavaScript reads the bytes and does something browser-shaped with them.

src/main.js
m.processImage('/opfs/myapp/uploads/photo.jpg');
 
const bytes = m.getFileBytes('/opfs/myapp/uploads/photo.processed.jpg');
const url = URL.createObjectURL(new Blob([bytes], { type: 'image/jpeg' }));
imgEl.src = url;

Per-runtime cheat sheet

Runtime/opfs/.../memfs/...Notes
Browser, no workerthrowsyestab-session memory only
Browser + useWorker: trueyes, or falls back to /memfs/yesthe persistent option
Node.jsn/an/am.FS reads and writes real disk
Cloudflare Workers / edgen/ayesper-invocation memory, no persistence
React Nativen/an/athe app sandbox, through the platform APIs

Pitfalls

  • Mounting `/opfs` without a worker throws inside getFinalPath(). Either set useWorker: true or write under /memfs/.
  • Setting `fs: { opfs: false }` and then using `/opfs/...` throws too - it is disabled, not missing.
  • Dropping the `<app>` segment. Writes to /memfs/foo work but sit outside the tree that gets cleaned up on terminate.
  • Expecting OPFS to cross origins. It does not: files written by one origin are invisible to another.
  • Needing durable files on the edge. There is no persistent store there; read bytes from R2/KV/S3 and write them in.
Type to search every guide page and section.
↑↓ navigate↵ openesc close