Skip to content

Commit

Permalink
Add Module['scriptDirectory'] to fix loading files that should be rel…
Browse files Browse the repository at this point in the history
…ative to main .js file on Node.js.
  • Loading branch information
juj committed Feb 2, 2018
1 parent 6d2798e commit a3c1d77
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 0 deletions.
2 changes: 2 additions & 0 deletions emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2553,6 +2553,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) {
Module['print']('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 @@ -259,6 +259,7 @@ var LibraryPThread = {
// of these are passed, then the default URL 'pthread-main.js' relative to the main html file is loaded.
if (typeof Module['locateFile'] === 'function') pthreadMainJs = Module['locateFile'](pthreadMainJs);
else if (Module['pthreadMainPrefixURL']) pthreadMainJs = Module['pthreadMainPrefixURL'] + pthreadMainJs;
pthreadMainJs = joinUrl(Module['scriptDirectory'], pthreadMainJs);
var worker = new Worker(pthreadMainJs);

worker.onmessage = function(e) {
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 @@ -833,6 +833,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 @@ -1994,6 +2006,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 @@ -88,6 +88,8 @@ var currentScriptUrl = (typeof document !== 'undefined' && document.currentScrip
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 @@ -8118,3 +8118,56 @@ def test_noderawfs_disables_embedding(self):
assert expected in err
err = run_process(base + ['--embed-files', 'somefile'], stderr=PIPE, check=False).stderr
assert expected in err

# 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 @@ -848,6 +848,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

0 comments on commit a3c1d77

Please sign in to comment.