emscripten-core / emscripten-core/emscripten
Web workers in next.js fail with a ReferenceError
- 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
Assessment
This issue has not been assessed yet.