add MODULARIZE option to wrap code in a function, and avoid polluting/using the global scope; #3167

This commit is contained in:
Alon Zakai 2015-02-03 11:30:48 -08:00
Родитель d9026e57a5
Коммит 6a736486b2
4 изменённых файлов: 77 добавлений и 0 удалений

15
emcc
Просмотреть файл

@ -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:

Просмотреть файл

@ -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.

Просмотреть файл

@ -0,0 +1,9 @@
#include<stdio.h>
int main() {
printf("hello, world!\n");
int result = 0;
REPORT_RESULT();
return 0;
}

Просмотреть файл

@ -2462,3 +2462,33 @@ window.close = function() {
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')