Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix_relative_file_loads_node_js #5484

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2713,6 +2713,8 @@ def generate_html(target, options, js_target, target_basename,
} else if (Module['memoryInitializerPrefixURL']) {
memoryInitializer = Module['memoryInitializerPrefixURL'] + memoryInitializer;
}
// If URL to memory initializer is relative, treat it relative with respect to Module['scriptDirectory'], if that is present.
if (Module['scriptDirectory'] && !/^(?:[a-z]+:)?[\/\\\\]\/?/i.test(memoryInitializer)) memoryInitializer = Module['scriptDirectory'] + memoryInitializer;
Module['memoryInitializerRequestURL'] = memoryInitializer;
var meminitXHR = Module['memoryInitializerRequest'] = new XMLHttpRequest();
meminitXHR.open('GET', memoryInitializer, true);
Expand Down
1 change: 1 addition & 0 deletions src/Fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ var Fetch = {
// of these are passed, then the default URL 'pthread-main.js' relative to the main html file is loaded.
if (typeof Module['locateFile'] === 'function') fetchJs = Module['locateFile'](fetchJs);
else if (Module['pthreadMainPrefixURL']) fetchJs = Module['pthreadMainPrefixURL'] + fetchJs;
fetchJs = joinUrl(Module['scriptDirectory'], fetchJs);
Fetch.worker = new Worker(fetchJs);
Fetch.worker.onmessage = function(e) {
out('fetch-worker sent a message: ' + e.filename + ':' + e.lineno + ': ' + e.message);
Expand Down
1 change: 1 addition & 0 deletions src/library_debugger_toolkit.js
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ var CyberDWARFHeapPrinter = function(cdFileLocation) {
} else if (Module['cdInitializerPrefixURL']) {
cdFileLocation = Module['cdInitializerPrefixURL'] + cdFileLocation;
}
cdFileLocation = joinUrl(Module['scriptDirectory'], cdFileLocation);
if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) {
var data = Module['read'](cdFileLocation);
install_cyberdwarf(data);
Expand Down
1 change: 1 addition & 0 deletions src/library_pthread.js
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ var LibraryPThread = {
else if (Module['pthreadMainPrefixURL']) pthreadMainJs = Module['pthreadMainPrefixURL'] + pthreadMainJs;

for (var i = 0; i < numWorkers; ++i) {
pthreadMainJs = joinUrl(Module['scriptDirectory'], pthreadMainJs);
var worker = new Worker(pthreadMainJs);

(function(worker) {
Expand Down
2 changes: 2 additions & 0 deletions src/postamble.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ if (memoryInitializer) {
} else if (Module['memoryInitializerPrefixURL']) {
memoryInitializer = Module['memoryInitializerPrefixURL'] + memoryInitializer;
}
memoryInitializer = joinUrl(Module['scriptDirectory'], memoryInitializer);
}

if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) {
var data = Module['readBinary'](memoryInitializer);
HEAPU8.set(data, GLOBAL_BASE);
Expand Down
15 changes: 15 additions & 0 deletions src/preamble.js
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,18 @@ function stackTrace() {
return demangleAll(js);
}

function isAbsolutePath(path) {
return isDataURI(path) || /^(?:[a-z]+:)?[\/\\]\/?/i.test(path);
}

// Joins relative URL 'b' to URL 'a'. 'a' may be empty, in which case 'b' is returned.
// If 'b' is an absolute URL, then 'a' is ignored and 'b' is returned as-is as well.
function joinUrl(a, b) {
#if ASSERTIONS
if (a && !a.endsWith('/')) throw 'First parameter to joinUrl() should end in /!';
#endif
return (a && !isAbsolutePath(b)) ? a + b : b;
}
// Memory management

var PAGE_SIZE = 16384;
Expand Down Expand Up @@ -2031,6 +2043,9 @@ function integrateWasmJS() {
asmjsCodeFile = Module['locateFile'](asmjsCodeFile);
}
}
wasmTextFile = joinUrl(Module['scriptDirectory'], wasmTextFile);
wasmBinaryFile = joinUrl(Module['scriptDirectory'], wasmBinaryFile);
asmjsCodeFile = joinUrl(Module['scriptDirectory'], asmjsCodeFile);

// utilities

Expand Down
2 changes: 2 additions & 0 deletions src/shell.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ if (ENVIRONMENT_IS_NODE) {

// Expose functionality in the same simple way that the shells work
// Note that we pollute the global namespace here, otherwise we break in node
if (!Module['scriptDirectory']) Module['scriptDirectory'] = __dirname + '/';

var nodeFS;
var nodePath;

Expand Down
53 changes: 53 additions & 0 deletions tests/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -8539,3 +8539,56 @@ def test_html_preprocess(self):
T4:NO_EXIT_RUNTIME > 1
T5:NO_EXIT_RUNTIME
T6:(else) !NO_EXIT_RUNTIME""", output)

# Tests that Emscripten-compiled applications can be run from a relative path with node command line that is different than the current working directory.
def test_node_js_run_from_different_directory(self):
args = ['-O3', '-s', 'WASM=1', '--memory-init-file', '1', '-s', 'BINARYEN_METHOD="asmjs,native-wasm"']
# Test that .mem.js is loaded up properly even if running the build output from a separate directory.
os.mkdir('subdir')
Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-o', os.path.join('subdir', 'a.js')] + args).communicate()
ret = Popen(NODE_JS + [os.path.join('subdir', 'a.js')], stdout=PIPE).communicate()[0]
try_delete('subdir')
assert 'hello, world!' in ret

# Test that the build is loaded properly when Module.locateFile is being used, where Module.locateFile() specifies an absolute path already.
os.mkdir('subdir')
open(os.path.join('subdir', 'pre.js'), 'w').write('''
var Module = {};
Module.memoryInitializerPrefixURL = 'this_should_be_getting_ignored_since_locateFile_is_specified/';
Module.locateFile = function(f) { return __dirname + '/' + f; }
''')

Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-o', os.path.join('subdir', 'a.js'), '--pre-js', os.path.join('subdir', 'pre.js')] + args).communicate()
ret = Popen(NODE_JS + [os.path.join('subdir', 'a.js')], stdout=PIPE).communicate()[0]
try_delete('subdir')
assert 'hello, world!' in ret

# Test that the build is loaded properly when Module.locateFile is being used, and it returns a relative path.
os.mkdir('subdir')
open(os.path.join('subdir', 'pre.js'), 'w').write('''
var Module = {};
Module.memoryInitializerPrefixURL = 'this_should_be_getting_ignored_since_locateFile_is_specified/';
Module.locateFile = function(f) { return 'data/' + f; }
''')

Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-o', os.path.join('subdir', 'a.js'), '--pre-js', os.path.join('subdir', 'pre.js')] + args).communicate()
os.mkdir(os.path.join('subdir', 'data'))
os.rename(os.path.join('subdir', 'a.js.mem'), os.path.join('subdir', 'data', 'a.js.mem'))
os.rename(os.path.join('subdir', 'a.asm.js'), os.path.join('subdir', 'data', 'a.asm.js'))
ret = Popen(NODE_JS + [os.path.join('subdir', 'a.js')], stdout=PIPE).communicate()[0]
try_delete('subdir')
assert 'hello, world!' in ret

# Test that the build is loaded properly when memoryInitializerPrefixURL is being used, and it returns a relative path.
os.mkdir('subdir')
open(os.path.join('subdir', 'pre.js'), 'w').write('''
var Module = {};
Module.memoryInitializerPrefixURL = 'data/';
''')

Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-o', os.path.join('subdir', 'a.js'), '--pre-js', os.path.join('subdir', 'pre.js')] + args).communicate()
os.mkdir(os.path.join('subdir', 'data'))
os.rename(os.path.join('subdir', 'a.js.mem'), os.path.join('subdir', 'data', 'a.js.mem'))
ret = Popen(NODE_JS + [os.path.join('subdir', 'a.js')], stdout=PIPE).communicate()[0]
try_delete('subdir')
assert 'hello, world!' in ret
1 change: 1 addition & 0 deletions tools/file_packager.py
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@ def was_seen(name):
var REMOTE_METADATA_NAME = typeof Module['locateFile'] === 'function' ?
Module['locateFile']('%(metadata_file)s') :
((Module['filePackagePrefixURL'] || '') + '%(metadata_file)s');
REMOTE_METADATA_NAME = joinUrl(Module['scriptDirectory'], REMOTE_METADATA_NAME);
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
Expand Down