Skip to content

Commit

Permalink
add MODULARIZE option to wrap code in a function, and avoid polluting…
Browse files Browse the repository at this point in the history
…/using the global scope; #3167
  • Loading branch information
kripken committed Feb 3, 2015
1 parent d9026e5 commit 6a73648
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 0 deletions.
15 changes: 15 additions & 0 deletions emcc
Original file line number Diff line number Diff line change
Expand Up @@ -1547,6 +1547,21 @@ try:

log_time('js opts')

if shared.Settings.MODULARIZE:
logging.debug('Modularizing, assigning to var ' + shared.Settings.EXPORT_NAME)
src = open(final).read()
final = final + '.modular.js'
f = open(final, 'w')
f.write('var ' + shared.Settings.EXPORT_NAME + ' = function(Module) {\n')
f.write(' Module = Module || {};\n')
f.write('\n')
f.write(src)
f.write('\n')
f.write(' return Module;\n')
f.write('}\n')
f.close()
src = None

js_target = unsuffixed(target) + '.js'

if shared.Settings.EMTERPRETIFY:
Expand Down
23 changes: 23 additions & 0 deletions src/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,29 @@ var HEADLESS = 0; // If 1, will include shim code that tries to 'fake' a browser
var DETERMINISTIC = 0; // If 1, we force Date.now(), Math.random, etc. to return deterministic
// results. Good for comparing builds for debugging purposes (and nothing else)

var MODULARIZE = 0; // By default we emit all code in a straightforward way into the output
// .js file. That means that if you load that in a script tag in a web
// page, it will use the global scope. With MODULARIZE set, we will instead emit
//
// var EXPORT_NAME = function(Module) {
// Module = Module || {};
// // .. all the emitted code from emscripten ..
// return Module;
// };
//
// where EXPORT_NAME is from the option of the same name (so, by default
// it will be var Module = ..., and so you should change EXPORT_NAME if
// you want more than one module in the same web page).
//
// You can then use this by something like
//
// var instance = EXPORT_NAME();
//
// or
//
// var instance = EXPORT_NAME({ option: value, ... });
//

var BENCHMARK = 0; // If 1, will just time how long main() takes to execute, and not
// print out anything at all whatsoever. This is useful for benchmarking.

Expand Down
9 changes: 9 additions & 0 deletions tests/browser_test_hello_world.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include<stdio.h>

int main() {
printf("hello, world!\n");
int result = 0;
REPORT_RESULT();
return 0;
}

30 changes: 30 additions & 0 deletions tests/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2462,3 +2462,33 @@ def test_emterpreter_async_virtual(self):
def test_emterpreter_async_virtual_2(self):
self.btest('emterpreter_async_virtual_2.cpp', '1', args=['-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-O3', '-s', 'ASSERTIONS=1', '-s', 'SAFE_HEAP=1', '-profiling'])

def test_modularize(self):
for opts in [[], ['-O1'], ['-O2', '-profiling'], ['-O2']]:
for args, code in [
([], 'Module();'), # defaults
(['-s', 'EXPORT_NAME="HelloWorld"'], '''
if (typeof Module !== "undefined") throw "what?!"; // do not pollute the global scope, we are modularized!
HelloWorld();
'''), # use EXPORT_NAME
(['-s', 'EXPORT_NAME="HelloWorld"'], '''
var hello = HelloWorld({ noInitialRun: true, onRuntimeInitialized: function() {
setTimeout(function() { hello._main(); }); // must be async, because onRuntimeInitialized may be called synchronously, so |hello| is not yet set!
} });
'''), # pass in a Module option (which prevents main(), which we then invoke ourselves)
(['-s', 'EXPORT_NAME="HelloWorld"', '--memory-init-file', '0'], '''
var hello = HelloWorld({ noInitialRun: true});
hello._main();
'''), # similar, but without a mem init file, everything is sync and simple
]:
print 'test on', opts, args, code
src = open(path_from_root('tests', 'browser_test_hello_world.c')).read()
open('test.c', 'w').write(self.with_report_result(src))
Popen([PYTHON, EMCC, 'test.c', '-s', 'MODULARIZE=1'] + args + opts).communicate()
open('a.html', 'w').write('''
<script src="a.out.js"></script>
<script>
%s
</script>
''' % code)
self.run_browser('a.html', '...', '/report_result?0')

0 comments on commit 6a73648

Please sign in to comment.