Given the following emscripten-bug.cpp
#include <random>
#include <iostream>
#ifdef __cplusplus
extern "C" {
#endif
void emscripten_test() {
std::random_device rd;
// Fails on windows if NODERAWFS is enabled
std::cerr << "Random " << rd() << "\n";
std::cerr << "Random " << rd() << "\n";
std::cerr << "Random " << rd() << "\n";
}
#ifdef __cplusplus
}
#endif
Compiled via
em++ -Wall -O3 -pipe -DNDEBUG -fomit-frame-pointer -std=c++11 -c \
-o build/emscripten-bug.o emscripten-bug.cpp
emcc build/emscripten-bug.o -o build/emscripten-bug.js \
--js-opts 0 -O3 \
-s WASM=0 \
-s DETERMINISTIC=1 \
-s EXPORTED_FUNCTIONS="['_emscripten_test']" \
-s USE_CLOSURE_COMPILER=0 \
-s ALLOW_MEMORY_GROWTH=1 \
-s ENVIRONMENT=node \
-s NODERAWFS=1 \
--memory-init-file 0
And invoked by
const sass = require('./build/emscripten-bug');
sass._emscripten_test();
This fails to work on windows. Either removing the random_device or using NODERAWFS=0 fixes the problem, but I really want to have both :/
The reason why it fails is because NODERAWFS overwrites the virtual FS with the following code:
if (ENVIRONMENT_IS_NODE) {
var _wrapNodeError = function(func) {
return function() {
try {
return func.apply(this, arguments)
} catch (e) {
if (!e.code) throw e;
throw new FS.ErrnoError(ERRNO_CODES[e.code]);
}
}
};
var VFS = Object.assign({}, FS);
for (var _key in NODERAWFS) {
FS[_key] = _wrapNodeError(NODERAWFS[_key]);
}
} else {
throw new Error("NODERAWFS is currently only supported on Node.js environment.");
}
The error happens when it tries to read /dev/urandom. Logically this file will not be available on windows and it seems that's why the original virtual FS defines those directly via:
FS.createDevice('/dev', 'random', random_device);
FS.createDevice('/dev', 'urandom', random_device);
So instead of using the "shimmed" device it tries to use the real ones.
The fix seems somewhat simple, but I'm not sure what the best way is.
I think it's reasonable to use the VFS for dev and proc even if NODERAWFS is enabled, as those are probably never really portable. Maybe another flag is needed (or use NODERAWFS=2) so users can decide whether they want to use "emulated" dev and proc instead of real ones.
Following is a quick hack/hotfix to get it working:
if (ENVIRONMENT_IS_NODE) {
var VFS = Object.assign({}, FS);
var _wrapNodeError = function(key, func) {
return function() {
if (arguments.length && arguments['0'].match && arguments['0'].match(/^\/+(?:dev|proc)\//)) {
return VFS[key].apply(this, arguments);
}
try {
return func.apply(this, arguments)
} catch (e) {
if (!e.code) throw e;
throw new FS.ErrnoError(ERRNO_CODES[e.code]);
}
}
};
for (var _key in NODERAWFS) {
FS[_key] = _wrapNodeError(_key, NODERAWFS[_key]);
}
} else {
throw new Error("NODERAWFS is currently only supported on Node.js environment.");
}
I might even be able to come up with a PR once it's decided how you want to move forward with this. Thank you and have a nice day!
Given the following emscripten-bug.cpp
Compiled via
And invoked by
This fails to work on windows. Either removing the
random_deviceor usingNODERAWFS=0fixes the problem, but I really want to have both :/The reason why it fails is because
NODERAWFSoverwrites the virtual FS with the following code:The error happens when it tries to read
/dev/urandom. Logically this file will not be available on windows and it seems that's why the original virtual FS defines those directly via:So instead of using the "shimmed" device it tries to use the real ones.
The fix seems somewhat simple, but I'm not sure what the best way is.
I think it's reasonable to use the VFS for
devandproceven ifNODERAWFSis enabled, as those are probably never really portable. Maybe another flag is needed (or useNODERAWFS=2) so users can decide whether they want to use "emulated"devandprocinstead of real ones.Following is a quick hack/hotfix to get it working:
I might even be able to come up with a PR once it's decided how you want to move forward with this. Thank you and have a nice day!