emscripten-core / emscripten-core/emscripten

Web workers in next.js fail with a ReferenceError

Open
#19,996 3 comments 1 reaction 0 assignees View on GitHub
Dominant language
C++
Stars
27.6k
Forks
3.6k
Avg merge
1d 1h
Merged PRs (30d)
105

Description

**Version of emscripten/emsdk:**
```
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.44-git
clang version 17.0.0 (https://github.com/llvm/llvm-project.git a8cbd27d1f238e104a5d5ca345d93bc1f4d4ab1f)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /usr/local/Cellar/emscripten/3.1.44/libexec/llvm/bin
```

**Failing command line:**

```
em++ \
-v \
--std=c++11 \
-lembind \
-s ENVIRONMENT='web,worker' \
-sEXPORT_ES6 -s USE_ES6_IMPORT_META=0 \
-sALLOW_MEMORY_GROWTH \
-sMODULARIZE \
--preload-file ... \
```

**Explanation:**

When using code generated by emscripten in a web worker under next.js with a preloaded file, the following error happens:

```
*****_worker.ts:51 Uncaught (in promise) ReferenceError: window is not defined
at loadPackage (*****.js:55:19)
at eval (*****.js:208:5)
at eval (*****.js:210:3)
```

The generated piece of code that throws the error is the following:

```
(function() {
// Do not attempt to redownload the virtual filesystem data when in a pthread or a Wasm Worker context.
if (Module['ENVIRONMENT_IS_PTHREAD'] || Module['$ww']) return;
var loadPackage = function(metadata) {

var PACKAGE_PATH = '';
if (typeof window === 'object') {
PACKAGE_PATH = window['encodeURIComponent'](window.location.pathname.toString().substring(0, window.location.pathname.toString().lastIndexOf('/')) + '/');
} else if (typeof process === 'undefined' && typeof location !== 'undefined') {
// web worker
PACKAGE_PATH = encodeURIComponent(location.pathname.toString().substring(0, location.pathname.toString().lastIndexOf('/')) + '/');
}
var PACKAGE_NAME = '*****.data';
var REMOTE_PACKAGE_BASE = '*****.data';
...
```

**The underlying problem seems to actually be in Next.js**, under which in web wokers `typeof window === 'object'` is indeed true. See the discussion: https://github.com/vercel/next.js/discussions/39605

For now, I use a workaround in my web worker to set a fake window containing the functions used by emscripten:

```
global.window = {
encodeURIComponent: encodeURIComponent,
location: location,
};
```

I understand that the place to fix this is next.js, but I wanted to leave a trace here for people facing this problem. Please, feel free to close as wontfix.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.