summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--CONTRIBUTING.markdown5
-rwxr-xr-xemcc6
-rwxr-xr-xemscripten.py2
-rw-r--r--src/analyzer.js2
-rw-r--r--src/intertyper.js10
-rw-r--r--src/jsifier.js6
-rw-r--r--src/library.js92
-rw-r--r--src/library_browser.js70
-rw-r--r--src/library_fs.js44
-rw-r--r--src/library_gl.js118
-rw-r--r--src/library_glut.js2
-rw-r--r--src/library_idbfs.js26
-rw-r--r--src/library_memfs.js6
-rw-r--r--src/library_sdl.js54
-rw-r--r--src/library_sockfs.js10
-rw-r--r--src/parseTools.js74
-rw-r--r--src/preamble.js6
-rw-r--r--src/proxyClient.js2
-rw-r--r--src/proxyWorker.js20
-rw-r--r--src/runtime.js4
-rw-r--r--src/settings.js3
-rw-r--r--src/shell.js22
-rw-r--r--system/include/emscripten/vector.h10
-rw-r--r--tests/cases/caall.ll2
-rw-r--r--tests/cases/selectadd.ll29
-rw-r--r--tests/cubegeom.c6
-rw-r--r--tests/mmap_file.c27
-rw-r--r--tests/test_browser.py11
-rw-r--r--tests/test_core.py151
-rw-r--r--tests/test_other.py98
-rw-r--r--tests/test_sanity.py6
-rw-r--r--tests/test_sockets.py26
-rw-r--r--tools/file_packager.py23
-rw-r--r--tools/shared.py2
35 files changed, 625 insertions, 351 deletions
diff --git a/AUTHORS b/AUTHORS
index 18124a6c..5c49e65e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -105,4 +105,5 @@ a license to everyone to use it as detailed in LICENSE.)
* Remi Papillie <remi.papillie@gmail.com>
* Fraser Adams <fraser.adams@blueyonder.co.uk>
* Michael Tirado <icetooth333@gmail.com>
+* Ben Noordhuis <info@bnoordhuis.nl>
diff --git a/CONTRIBUTING.markdown b/CONTRIBUTING.markdown
new file mode 100644
index 00000000..ceea8735
--- /dev/null
+++ b/CONTRIBUTING.markdown
@@ -0,0 +1,5 @@
+
+See our wiki for information about contributing to Emscripten:
+
+[Contribution section on wiki](https://github.com/kripken/emscripten/wiki#contributing)
+
diff --git a/emcc b/emcc
index 3406ff83..8f8ad4aa 100755
--- a/emcc
+++ b/emcc
@@ -777,6 +777,7 @@ try:
save_bc = False
memory_init_file = False
use_preload_cache = False
+ no_heap_copy = False
proxy_to_worker = False
if use_cxx:
@@ -897,6 +898,9 @@ try:
elif newargs[i].startswith('--use-preload-cache'):
use_preload_cache = True
newargs[i] = ''
+ elif newargs[i].startswith('--no-heap-copy'):
+ no_heap_copy = True
+ newargs[i] = ''
elif newargs[i] == '--ignore-dynamic-linking':
ignore_dynamic_linking = True
newargs[i] = ''
@@ -1667,6 +1671,8 @@ try:
file_args += ['--compress', Compression.encoder, Compression.decoder, Compression.js_name]
if use_preload_cache:
file_args.append('--use-preload-cache')
+ if no_heap_copy:
+ file_args.append('--no-heap-copy')
file_code = execute([shared.PYTHON, shared.FILE_PACKAGER, unsuffixed(target) + '.data'] + file_args, stdout=PIPE)[0]
pre_js = file_code + pre_js
diff --git a/emscripten.py b/emscripten.py
index dbea6eb2..5576baba 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -578,7 +578,7 @@ var asm = (function(global, env, buffer) {
var HEAPU32 = new global.Uint32Array(buffer);
var HEAPF32 = new global.Float32Array(buffer);
var HEAPF64 = new global.Float64Array(buffer);
-''' % (asm_setup, "'use asm';" if not forwarded_json['Types']['hasInlineJS'] and not settings['SIDE_MODULE'] else "'almost asm';") + '\n' + asm_global_vars + '''
+''' % (asm_setup, "'use asm';" if not forwarded_json['Types']['hasInlineJS'] and not settings['SIDE_MODULE'] and settings['ASM_JS'] == 1 else "'almost asm';") + '\n' + asm_global_vars + '''
var __THREW__ = 0;
var threwValue = 0;
var setjmpId = 0;
diff --git a/src/analyzer.js b/src/analyzer.js
index 2b74a83f..253c5505 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -418,7 +418,7 @@ function analyzer(data, sidePass) {
toAdd.push({
intertype: 'value',
assignTo: element.ident,
- type: element.bits,
+ type: 'i' + element.bits,
ident: 'tempRet' + (j - 1)
});
assert(j<10); // TODO: dynamically create more than 10 tempRet-s
diff --git a/src/intertyper.js b/src/intertyper.js
index d3640889..fceeb38d 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -682,7 +682,7 @@ function intertyper(lines, sidePass, baseLineNums) {
}
if (item.assignTo) item.ident = 'return ' + item.ident;
item.ident = '(function(' + params + ') { ' + item.ident + ' })(' + args + ');';
- return { forward: null, ret: item, item: item };
+ return { ret: item, item: item };
}
if (item.ident.substr(-2) == '()') {
// See comment in isStructType()
@@ -705,13 +705,12 @@ function intertyper(lines, sidePass, baseLineNums) {
if (item.indent == 2) {
// standalone call - not in assign
item.standalone = true;
- return { forward: null, ret: item, item: item };
+ return { ret: item, item: item };
}
- return { forward: item, ret: null, item: item };
+ return { ret: null, item: item };
}
function callHandler(item) {
var result = makeCall.call(this, item, 'call');
- if (result.forward) this.forwardItem(result.forward, 'Reintegrator');
return result.ret;
}
function invokeHandler(item) {
@@ -721,10 +720,9 @@ function intertyper(lines, sidePass, baseLineNums) {
finalResults.push({
intertype: 'branch',
label: result.item.toLabel,
- lineNum: (result.forward ? item.parentLineNum : item.lineNum) + 0.5
+ lineNum: item.lineNum + 0.5
});
}
- if (result.forward) this.forwardItem(result.forward, 'Reintegrator');
return result.ret;
}
function atomicHandler(item) {
diff --git a/src/jsifier.js b/src/jsifier.js
index ec7ad1c2..0da48a8c 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -953,7 +953,7 @@ function JSify(data, functionsOnly, givenFunctions) {
return '(' + makeSetValue(item.ident, 0, value + '.x', native, 0, 0, item.align) + ',' +
makeSetValue(item.ident, 4, value + '.y', native, 0, 0, item.align) + ',' +
makeSetValue(item.ident, 8, value + '.z', native, 0, 0, item.align) + ',' +
- makeSetValue(item.ident, 12, value + '.w', native, 0, 0, item.align) + ')';
+ makeSetValue(item.ident, 12, value + '.w', native, 0, 0, item.align) + ');';
}
switch (impl) {
case VAR_NATIVIZED:
@@ -1329,7 +1329,7 @@ function JSify(data, functionsOnly, givenFunctions) {
return base + '32x4(' + makeGetValue(value, 0, native, 0, item.unsigned, 0, item.align) + ',' +
makeGetValue(value, 4, native, 0, item.unsigned, 0, item.align) + ',' +
makeGetValue(value, 8, native, 0, item.unsigned, 0, item.align) + ',' +
- makeGetValue(value, 12, native, 0, item.unsigned, 0, item.align) + ')';
+ makeGetValue(value, 12, native, 0, item.unsigned, 0, item.align) + ');';
}
var impl = item.ident ? getVarImpl(item.funcData, item.ident) : VAR_EMULATED;
switch (impl) {
@@ -1491,7 +1491,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
params.forEach(function(param, i) {
- var val = finalizeParam(param);
+ var val = finalizeLLVMParameter(param);
if (!hasVarArgs || useJSArgs || i < normalArgs) {
args.push(val);
argsTypes.push(param.type);
diff --git a/src/library.js b/src/library.js
index 6eab2587..501f766c 100644
--- a/src/library.js
+++ b/src/library.js
@@ -1602,12 +1602,12 @@ LibraryManager.library = {
if (format.indexOf('%n') >= 0) {
// need to track soFar
var _get = get;
- get = function() {
+ get = function get() {
soFar++;
return _get();
}
var _unget = unget;
- unget = function() {
+ unget = function unget() {
soFar--;
return _unget();
}
@@ -2755,12 +2755,12 @@ LibraryManager.library = {
return -1;
}
var buffer = [];
- var get = function() {
+ function get() {
var c = _fgetc(stream);
buffer.push(c);
return c;
};
- var unget = function() {
+ function unget() {
_ungetc(buffer.pop(), stream);
};
return __scanString(format, get, unget, varargs);
@@ -2777,8 +2777,8 @@ LibraryManager.library = {
// int sscanf(const char *restrict s, const char *restrict format, ... );
// http://pubs.opengroup.org/onlinepubs/000095399/functions/scanf.html
var index = 0;
- var get = function() { return {{{ makeGetValue('s', 'index++', 'i8') }}}; };
- var unget = function() { index--; };
+ function get() { return {{{ makeGetValue('s', 'index++', 'i8') }}}; };
+ function unget() { index--; };
return __scanString(format, get, unget, varargs);
},
snprintf__deps: ['_formatString'],
@@ -3040,7 +3040,7 @@ LibraryManager.library = {
},
bsearch: function(key, base, num, size, compar) {
- var cmp = function(x, y) {
+ function cmp(x, y) {
#if ASM_JS
return Module['dynCall_iii'](compar, x, y);
#else
@@ -5108,7 +5108,7 @@ LibraryManager.library = {
table[from + i] = {};
sigs.forEach(function(sig) { // TODO: new Function etc.
var full = 'dynCall_' + sig;
- table[from + i][sig] = function() {
+ table[from + i][sig] = function dynCall_sig() {
arguments[0] -= from;
return asm[full].apply(null, arguments);
}
@@ -5132,7 +5132,7 @@ LibraryManager.library = {
// patch js module dynCall_* to use functionTable
sigs.forEach(function(sig) {
- jsModule['dynCall_' + sig] = function() {
+ jsModule['dynCall_' + sig] = function dynCall_sig() {
return table[arguments[0]][sig].apply(null, arguments);
};
});
@@ -5295,6 +5295,16 @@ LibraryManager.library = {
}
},
+ dladdr: function(addr, info) {
+ // report all function pointers as coming from this program itself XXX not really correct in any way
+ var fname = allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_NORMAL); // XXX leak
+ {{{ makeSetValue('addr', 0, 'fname', 'i32') }}};
+ {{{ makeSetValue('addr', QUANTUM_SIZE, '0', 'i32') }}};
+ {{{ makeSetValue('addr', QUANTUM_SIZE*2, '0', 'i32') }}};
+ {{{ makeSetValue('addr', QUANTUM_SIZE*3, '0', 'i32') }}};
+ return 1;
+ },
+
// ==========================================================================
// pwd.h
// ==========================================================================
@@ -5596,7 +5606,7 @@ LibraryManager.library = {
var WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
var MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
- var leadingSomething = function(value, digits, character) {
+ function leadingSomething(value, digits, character) {
var str = typeof value === 'number' ? value.toString() : (value || '');
while (str.length < digits) {
str = character[0]+str;
@@ -5604,12 +5614,12 @@ LibraryManager.library = {
return str;
};
- var leadingNulls = function(value, digits) {
+ function leadingNulls(value, digits) {
return leadingSomething(value, digits, '0');
};
- var compareByDay = function(date1, date2) {
- var sgn = function(value) {
+ function compareByDay(date1, date2) {
+ function sgn(value) {
return value < 0 ? -1 : (value > 0 ? 1 : 0);
};
@@ -5622,7 +5632,7 @@ LibraryManager.library = {
return compare;
};
- var getFirstWeekStartDate = function(janFourth) {
+ function getFirstWeekStartDate(janFourth) {
switch (janFourth.getDay()) {
case 0: // Sunday
return new Date(janFourth.getFullYear()-1, 11, 29);
@@ -5641,7 +5651,7 @@ LibraryManager.library = {
}
};
- var getWeekBasedYear = function(date) {
+ function getWeekBasedYear(date) {
var thisDate = __addDays(new Date(date.tm_year+1900, 0, 1), date.tm_yday);
var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4);
@@ -5928,8 +5938,8 @@ LibraryManager.library = {
var matches = new RegExp('^'+pattern).exec(Pointer_stringify(buf))
// Module['print'](Pointer_stringify(buf)+ ' is matched by '+((new RegExp('^'+pattern)).source)+' into: '+JSON.stringify(matches));
- var initDate = function() {
- var fixup = function(value, min, max) {
+ function initDate() {
+ function fixup(value, min, max) {
return (typeof value !== 'number' || isNaN(value)) ? min : (value>=min ? (value<=max ? value: max): min);
};
return {
@@ -5946,7 +5956,7 @@ LibraryManager.library = {
var date = initDate();
var value;
- var getMatch = function(symbol) {
+ function getMatch(symbol) {
var pos = capture.indexOf(symbol);
// check if symbol appears in regexp
if (pos >= 0) {
@@ -6876,6 +6886,10 @@ LibraryManager.library = {
pthread_mutex_trylock: function() {
return 0;
},
+ pthread_mutexattr_setpshared: function(attr, pshared) {
+ // XXX implement if/when getpshared is required
+ return 0;
+ },
pthread_cond_init: function() {},
pthread_cond_destroy: function() {},
pthread_cond_broadcast: function() {
@@ -6971,6 +6985,10 @@ LibraryManager.library = {
_pthread_cleanup_push.level = __ATEXIT__.length;
},
+ pthread_rwlock_init: function() {
+ return 0; // XXX
+ },
+
// ==========================================================================
// malloc.h
// ==========================================================================
@@ -7681,7 +7699,7 @@ LibraryManager.library = {
var session = Module['webrtc']['session'];
var peer = new Peer(broker);
var listenOptions = Module['webrtc']['hostOptions'] || {};
- peer.onconnection = function(connection) {
+ peer.onconnection = function peer_onconnection(connection) {
console.log('connected');
var addr;
/* If this peer is connecting to the host, assign 10.0.0.1 to the host so it can be
@@ -7695,7 +7713,7 @@ LibraryManager.library = {
}
connection['addr'] = addr;
Sockets.connections[addr] = connection;
- connection.ondisconnect = function() {
+ connection.ondisconnect = function connection_ondisconnect() {
console.log('disconnect');
// Don't return the host address (10.0.0.1) to the pool
if (!(session && session === Sockets.connections[addr]['route'])) {
@@ -7707,12 +7725,12 @@ LibraryManager.library = {
Module['webrtc']['ondisconnect'](peer);
}
};
- connection.onerror = function(error) {
+ connection.onerror = function connection_onerror(error) {
if (Module['webrtc']['onerror'] && 'function' === typeof Module['webrtc']['onerror']) {
Module['webrtc']['onerror'](error);
}
};
- connection.onmessage = function(label, message) {
+ connection.onmessage = function connection_onmessage(label, message) {
if ('unreliable' === label) {
handleMessage(addr, message.data);
}
@@ -7722,13 +7740,13 @@ LibraryManager.library = {
Module['webrtc']['onconnect'](peer);
}
};
- peer.onpending = function(pending) {
+ peer.onpending = function peer_onpending(pending) {
console.log('pending from: ', pending['route'], '; initiated by: ', (pending['incoming']) ? 'remote' : 'local');
};
- peer.onerror = function(error) {
+ peer.onerror = function peer_onerror(error) {
console.error(error);
};
- peer.onroute = function(route) {
+ peer.onroute = function peer_onroute(route) {
if (Module['webrtc']['onpeer'] && 'function' === typeof Module['webrtc']['onpeer']) {
Module['webrtc']['onpeer'](peer, route);
}
@@ -7744,7 +7762,7 @@ LibraryManager.library = {
console.log("unable to deliver message: ", addr, header[1], message);
}
}
- window.onbeforeunload = function() {
+ window.onbeforeunload = function window_onbeforeunload() {
var ids = Object.keys(Sockets.connections);
ids.forEach(function(id) {
Sockets.connections[id].close();
@@ -7813,7 +7831,7 @@ LibraryManager.library = {
}
info.addr = Sockets.localAddr; // 10.0.0.254
info.host = __inet_ntop4_raw(info.addr);
- info.close = function() {
+ info.close = function info_close() {
Sockets.portmap[info.port] = undefined;
}
Sockets.portmap[info.port] = info;
@@ -8545,7 +8563,13 @@ LibraryManager.library = {
return -1;
}
var arg = {{{ makeGetValue('varargs', '0', 'i32') }}};
- return FS.ioctl(stream, request, arg);
+
+ try {
+ return FS.ioctl(stream, request, arg);
+ } catch (e) {
+ FS.handleFSError(e);
+ return -1;
+ }
},
#endif
@@ -8578,7 +8602,7 @@ LibraryManager.library = {
},
emscripten_run_script_string: function(ptr) {
- var s = eval(Pointer_stringify(ptr));
+ var s = eval(Pointer_stringify(ptr)) + '';
var me = _emscripten_run_script_string;
if (!me.bufferSize || me.bufferSize < s.length+1) {
if (me.bufferSize) _free(me.buffer);
@@ -8621,6 +8645,14 @@ LibraryManager.library = {
},
//============================
+ // emscripten vector ops
+ //============================
+
+ emscripten_float32x4_signmask__inline: function(x) {
+ return x + '.signMask()';
+ },
+
+ //============================
// i64 math
//============================
@@ -8716,6 +8748,6 @@ function autoAddDeps(object, name) {
// Add aborting stubs for various libc stuff needed by libc++
['pthread_cond_signal', 'pthread_equal', 'wcstol', 'wcstoll', 'wcstoul', 'wcstoull', 'wcstof', 'wcstod', 'wcstold', 'pthread_join', 'pthread_detach', 'catgets', 'catopen', 'catclose', 'fputwc', '__lockfile', '__unlockfile'].forEach(function(aborter) {
- LibraryManager.library[aborter] = function() { throw 'TODO: ' + aborter };
+ LibraryManager.library[aborter] = function aborting_stub() { throw 'TODO: ' + aborter };
});
diff --git a/src/library_browser.js b/src/library_browser.js
index 59d2945e..b70dbc84 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -4,12 +4,12 @@
mergeInto(LibraryManager.library, {
$Browser__deps: ['$PATH'],
- $Browser__postset: 'Module["requestFullScreen"] = function(lockPointer, resizeCanvas) { Browser.requestFullScreen(lockPointer, resizeCanvas) };\n' + // exports
- 'Module["requestAnimationFrame"] = function(func) { Browser.requestAnimationFrame(func) };\n' +
- 'Module["setCanvasSize"] = function(width, height, noUpdates) { Browser.setCanvasSize(width, height, noUpdates) };\n' +
- 'Module["pauseMainLoop"] = function() { Browser.mainLoop.pause() };\n' +
- 'Module["resumeMainLoop"] = function() { Browser.mainLoop.resume() };\n' +
- 'Module["getUserMedia"] = function() { Browser.getUserMedia() }',
+ $Browser__postset: 'Module["requestFullScreen"] = function Module_requestFullScreen(lockPointer, resizeCanvas) { Browser.requestFullScreen(lockPointer, resizeCanvas) };\n' + // exports
+ 'Module["requestAnimationFrame"] = function Module_requestAnimationFrame(func) { Browser.requestAnimationFrame(func) };\n' +
+ 'Module["setCanvasSize"] = function Module_setCanvasSize(width, height, noUpdates) { Browser.setCanvasSize(width, height, noUpdates) };\n' +
+ 'Module["pauseMainLoop"] = function Module_pauseMainLoop() { Browser.mainLoop.pause() };\n' +
+ 'Module["resumeMainLoop"] = function Module_resumeMainLoop() { Browser.mainLoop.resume() };\n' +
+ 'Module["getUserMedia"] = function Module_getUserMedia() { Browser.getUserMedia() }',
$Browser: {
mainLoop: {
scheduler: null,
@@ -77,10 +77,10 @@ mergeInto(LibraryManager.library, {
// might create some side data structure for use later (like an Image element, etc.).
var imagePlugin = {};
- imagePlugin['canHandle'] = function(name) {
+ imagePlugin['canHandle'] = function imagePlugin_canHandle(name) {
return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name);
};
- imagePlugin['handle'] = function(byteArray, name, onload, onerror) {
+ imagePlugin['handle'] = function imagePlugin_handle(byteArray, name, onload, onerror) {
var b = null;
if (Browser.hasBlobConstructor) {
try {
@@ -103,7 +103,7 @@ mergeInto(LibraryManager.library, {
assert(typeof url == 'string', 'createObjectURL must return a url as a string');
#endif
var img = new Image();
- img.onload = function() {
+ img.onload = function img_onload() {
assert(img.complete, 'Image ' + name + ' could not be decoded');
var canvas = document.createElement('canvas');
canvas.width = img.width;
@@ -114,7 +114,7 @@ mergeInto(LibraryManager.library, {
Browser.URLObject.revokeObjectURL(url);
if (onload) onload(byteArray);
};
- img.onerror = function(event) {
+ img.onerror = function img_onerror(event) {
console.log('Image ' + url + ' could not be decoded');
if (onerror) onerror();
};
@@ -123,10 +123,10 @@ mergeInto(LibraryManager.library, {
Module['preloadPlugins'].push(imagePlugin);
var audioPlugin = {};
- audioPlugin['canHandle'] = function(name) {
+ audioPlugin['canHandle'] = function audioPlugin_canHandle(name) {
return !Module.noAudioDecoding && name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 };
};
- audioPlugin['handle'] = function(byteArray, name, onload, onerror) {
+ audioPlugin['handle'] = function audioPlugin_handle(byteArray, name, onload, onerror) {
var done = false;
function finish(audio) {
if (done) return;
@@ -152,7 +152,7 @@ mergeInto(LibraryManager.library, {
#endif
var audio = new Audio();
audio.addEventListener('canplaythrough', function() { finish(audio) }, false); // use addEventListener due to chromium bug 124926
- audio.onerror = function(event) {
+ audio.onerror = function audio_onerror(event) {
if (done) return;
console.log('warning: browser could not fully decode audio ' + name + ', trying slower base64 approach');
function encode64(data) {
@@ -268,7 +268,7 @@ mergeInto(LibraryManager.library, {
(function(prop) {
switch (typeof tempCtx[prop]) {
case 'function': {
- wrapper[prop] = function() {
+ wrapper[prop] = function gl_wrapper() {
if (GL.debug) {
var printArgs = Array.prototype.slice.call(arguments).map(Runtime.prettyPrint);
Module.printErr('[gl_f:' + prop + ':' + printArgs + ']');
@@ -360,15 +360,19 @@ mergeInto(LibraryManager.library, {
},
requestAnimationFrame: function(func) {
- if (!window.requestAnimationFrame) {
- window.requestAnimationFrame = window['requestAnimationFrame'] ||
- window['mozRequestAnimationFrame'] ||
- window['webkitRequestAnimationFrame'] ||
- window['msRequestAnimationFrame'] ||
- window['oRequestAnimationFrame'] ||
- window['setTimeout'];
+ if (typeof window === 'undefined') { // Provide fallback to setTimeout if window is undefined (e.g. in Node.js)
+ setTimeout(func, 1000/60);
+ } else {
+ if (!window.requestAnimationFrame) {
+ window.requestAnimationFrame = window['requestAnimationFrame'] ||
+ window['mozRequestAnimationFrame'] ||
+ window['webkitRequestAnimationFrame'] ||
+ window['msRequestAnimationFrame'] ||
+ window['oRequestAnimationFrame'] ||
+ window['setTimeout'];
+ }
+ window.requestAnimationFrame(func);
}
- window.requestAnimationFrame(func);
},
// generic abort-aware wrapper for an async callback
@@ -497,7 +501,7 @@ mergeInto(LibraryManager.library, {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
- xhr.onload = function() {
+ xhr.onload = function xhr_onload() {
if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
onload(xhr.response);
} else {
@@ -610,7 +614,7 @@ mergeInto(LibraryManager.library, {
http.responseType = 'arraybuffer';
// LOAD
- http.onload = function(e) {
+ http.onload = function http_onload(e) {
if (http.status == 200) {
FS.createDataFile( _file.substr(0, index), _file.substr(index + 1), new Uint8Array(http.response), true, true);
if (onload) Runtime.dynCall('vii', onload, [arg, file]);
@@ -620,12 +624,12 @@ mergeInto(LibraryManager.library, {
};
// ERROR
- http.onerror = function(e) {
+ http.onerror = function http_onerror(e) {
if (onerror) Runtime.dynCall('vii', onerror, [arg, http.status]);
};
// PROGRESS
- http.onprogress = function(e) {
+ http.onprogress = function http_onprogress(e) {
var percentComplete = (e.position / e.totalSize)*100;
if (onprogress) Runtime.dynCall('vii', onprogress, [arg, percentComplete]);
};
@@ -705,7 +709,7 @@ mergeInto(LibraryManager.library, {
assert(runDependencies === 0, 'async_load_script must be run when no other dependencies are active');
var script = document.createElement('script');
- script.onload = function() {
+ script.onload = function script_onload() {
if (runDependencies > 0) {
dependenciesFulfilled = onload;
} else {
@@ -720,7 +724,7 @@ mergeInto(LibraryManager.library, {
emscripten_set_main_loop: function(func, fps, simulateInfiniteLoop) {
Module['noExitRuntime'] = true;
- Browser.mainLoop.runner = function() {
+ Browser.mainLoop.runner = function Browser_mainLoop_runner() {
if (ABORT) return;
if (Browser.mainLoop.queue.length > 0) {
var start = Date.now();
@@ -777,11 +781,11 @@ mergeInto(LibraryManager.library, {
Browser.mainLoop.scheduler();
}
if (fps && fps > 0) {
- Browser.mainLoop.scheduler = function() {
+ Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler() {
setTimeout(Browser.mainLoop.runner, 1000/fps); // doing this each time means that on exception, we stop
}
} else {
- Browser.mainLoop.scheduler = function() {
+ Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler() {
Browser.requestAnimationFrame(Browser.mainLoop.runner);
}
}
@@ -870,14 +874,14 @@ mergeInto(LibraryManager.library, {
emscripten_get_now: function() {
if (!_emscripten_get_now.actual) {
if (ENVIRONMENT_IS_NODE) {
- _emscripten_get_now.actual = function() {
+ _emscripten_get_now.actual = function _emscripten_get_now_actual() {
var t = process['hrtime']();
return t[0] * 1e3 + t[1] / 1e6;
}
} else if (typeof dateNow !== 'undefined') {
_emscripten_get_now.actual = dateNow;
} else if (ENVIRONMENT_IS_WEB && window['performance'] && window['performance']['now']) {
- _emscripten_get_now.actual = function() { return window['performance']['now'](); };
+ _emscripten_get_now.actual = function _emscripten_get_now_actual() { return window['performance']['now'](); };
} else {
_emscripten_get_now.actual = Date.now;
}
@@ -895,7 +899,7 @@ mergeInto(LibraryManager.library, {
buffer: 0,
bufferSize: 0
};
- info.worker.onmessage = function(msg) {
+ info.worker.onmessage = function info_worker_onmessage(msg) {
var info = Browser.workers[id];
if (!info) return; // worker was destroyed meanwhile
var callbackId = msg.data['callbackId'];
diff --git a/src/library_fs.js b/src/library_fs.js
index aece2664..5412185f 100644
--- a/src/library_fs.js
+++ b/src/library_fs.js
@@ -361,9 +361,10 @@ mergeInto(LibraryManager.library, {
// SOCKFS is completed.
createStream: function(stream, fd_start, fd_end) {
if (!FS.FSStream) {
- FS.FSStream = {};
+ FS.FSStream = function(){};
+ FS.FSStream.prototype = {};
// compatibility
- Object.defineProperties(FS.FSStream, {
+ Object.defineProperties(FS.FSStream.prototype, {
object: {
get: function() { return this.node; },
set: function(val) { this.node = val; }
@@ -379,7 +380,16 @@ mergeInto(LibraryManager.library, {
}
});
}
- stream.prototype = FS.FSStream;
+ if (stream.__proto__) {
+ // reuse the object
+ stream.__proto__ = FS.FSStream.prototype;
+ } else {
+ var newStream = new FS.FSStream();
+ for (var p in stream) {
+ newStream[p] = stream[p];
+ }
+ stream = newStream;
+ }
var fd = FS.nextfd(fd_start, fd_end);
stream.fd = fd;
FS.streams[fd] = stream;
@@ -439,7 +449,7 @@ mergeInto(LibraryManager.library, {
var completed = 0;
var total = FS.mounts.length;
- var done = function(err) {
+ function done(err) {
if (err) {
return callback(err);
}
@@ -1326,11 +1336,11 @@ mergeInto(LibraryManager.library, {
if (typeof XMLHttpRequest !== 'undefined') {
if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc';
// Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse.
- var LazyUint8Array = function() {
+ function LazyUint8Array() {
this.lengthKnown = false;
this.chunks = []; // Loaded chunks. Index is the chunk number
}
- LazyUint8Array.prototype.get = function(idx) {
+ LazyUint8Array.prototype.get = function LazyUint8Array_get(idx) {
if (idx > this.length-1 || idx < 0) {
return undefined;
}
@@ -1338,10 +1348,10 @@ mergeInto(LibraryManager.library, {
var chunkNum = Math.floor(idx / this.chunkSize);
return this.getter(chunkNum)[chunkOffset];
}
- LazyUint8Array.prototype.setDataGetter = function(getter) {
+ LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) {
this.getter = getter;
}
- LazyUint8Array.prototype.cacheLength = function() {
+ LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() {
// Find length
var xhr = new XMLHttpRequest();
xhr.open('HEAD', url, false);
@@ -1437,7 +1447,7 @@ mergeInto(LibraryManager.library, {
var keys = Object.keys(node.stream_ops);
keys.forEach(function(key) {
var fn = node.stream_ops[key];
- stream_ops[key] = function() {
+ stream_ops[key] = function forceLoadLazyFile() {
if (!FS.forceLoadFile(node)) {
throw new FS.ErrnoError(ERRNO_CODES.EIO);
}
@@ -1445,7 +1455,7 @@ mergeInto(LibraryManager.library, {
};
});
// use a custom read function
- stream_ops.read = function(stream, buffer, offset, length, position) {
+ stream_ops.read = function stream_ops_read(stream, buffer, offset, length, position) {
if (!FS.forceLoadFile(node)) {
throw new FS.ErrnoError(ERRNO_CODES.EIO);
}
@@ -1539,12 +1549,12 @@ mergeInto(LibraryManager.library, {
} catch (e) {
return onerror(e);
}
- openRequest.onupgradeneeded = function() {
+ openRequest.onupgradeneeded = function openRequest_onupgradeneeded() {
console.log('creating db');
var db = openRequest.result;
db.createObjectStore(FS.DB_STORE_NAME);
};
- openRequest.onsuccess = function() {
+ openRequest.onsuccess = function openRequest_onsuccess() {
var db = openRequest.result;
var transaction = db.transaction([FS.DB_STORE_NAME], 'readwrite');
var files = transaction.objectStore(FS.DB_STORE_NAME);
@@ -1554,8 +1564,8 @@ mergeInto(LibraryManager.library, {
}
paths.forEach(function(path) {
var putRequest = files.put(FS.analyzePath(path).object.contents, path);
- putRequest.onsuccess = function() { ok++; if (ok + fail == total) finish() };
- putRequest.onerror = function() { fail++; if (ok + fail == total) finish() };
+ putRequest.onsuccess = function putRequest_onsuccess() { ok++; if (ok + fail == total) finish() };
+ putRequest.onerror = function putRequest_onerror() { fail++; if (ok + fail == total) finish() };
});
transaction.onerror = onerror;
};
@@ -1573,7 +1583,7 @@ mergeInto(LibraryManager.library, {
return onerror(e);
}
openRequest.onupgradeneeded = onerror; // no database to load from
- openRequest.onsuccess = function() {
+ openRequest.onsuccess = function openRequest_onsuccess() {
var db = openRequest.result;
try {
var transaction = db.transaction([FS.DB_STORE_NAME], 'readonly');
@@ -1588,7 +1598,7 @@ mergeInto(LibraryManager.library, {
}
paths.forEach(function(path) {
var getRequest = files.get(path);
- getRequest.onsuccess = function() {
+ getRequest.onsuccess = function getRequest_onsuccess() {
if (FS.analyzePath(path).exists) {
FS.unlink(path);
}
@@ -1596,7 +1606,7 @@ mergeInto(LibraryManager.library, {
ok++;
if (ok + fail == total) finish();
};
- getRequest.onerror = function() { fail++; if (ok + fail == total) finish() };
+ getRequest.onerror = function getRequest_onerror() { fail++; if (ok + fail == total) finish() };
});
transaction.onerror = onerror;
};
diff --git a/src/library_gl.js b/src/library_gl.js
index 6f145e91..7074f844 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -1682,7 +1682,7 @@ var LibraryGL = {
};
var glEnable = _glEnable;
- _glEnable = function(cap) {
+ _glEnable = function _glEnable(cap) {
// Clean up the renderer on any change to the rendering state. The optimization of
// skipping renderer setup is aimed at the case of multiple glDraw* right after each other
if (GL.immediate.lastRenderer) GL.immediate.lastRenderer.cleanup();
@@ -1704,7 +1704,7 @@ var LibraryGL = {
};
var glDisable = _glDisable;
- _glDisable = function(cap) {
+ _glDisable = function _glDisable(cap) {
if (GL.immediate.lastRenderer) GL.immediate.lastRenderer.cleanup();
if (cap == 0x0B60 /* GL_FOG */) {
GLEmulation.fogEnabled = false;
@@ -1722,7 +1722,7 @@ var LibraryGL = {
}
glDisable(cap);
};
- _glIsEnabled = function(cap) {
+ _glIsEnabled = function _glIsEnabled(cap) {
if (cap == 0x0B60 /* GL_FOG */) {
return GLEmulation.fogEnabled ? 1 : 0;
} else if (!(cap in validCapabilities)) {
@@ -1732,7 +1732,7 @@ var LibraryGL = {
};
var glGetBooleanv = _glGetBooleanv;
- _glGetBooleanv = function(pname, p) {
+ _glGetBooleanv = function _glGetBooleanv(pname, p) {
var attrib = GLEmulation.getAttributeFromCapability(pname);
if (attrib !== null) {
var result = GL.immediate.enabledClientAttributes[attrib];
@@ -1743,7 +1743,7 @@ var LibraryGL = {
};
var glGetIntegerv = _glGetIntegerv;
- _glGetIntegerv = function(pname, params) {
+ _glGetIntegerv = function _glGetIntegerv(pname, params) {
switch (pname) {
case 0x84E2: pname = Module.ctx.MAX_TEXTURE_IMAGE_UNITS /* fake it */; break; // GL_MAX_TEXTURE_UNITS
case 0x8B4A: { // GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB
@@ -1793,17 +1793,17 @@ var LibraryGL = {
return;
}
case 0x8088: { // GL_TEXTURE_COORD_ARRAY_SIZE
- var attribute = GLImmediate.clientAttributes[GLImmediate.TEXTURE0];
+ var attribute = GLImmediate.clientAttributes[GLImmediate.TEXTURE0 + GLImmediate.clientActiveTexture];
{{{ makeSetValue('params', '0', 'attribute ? attribute.size : 0', 'i32') }}};
return;
}
case 0x8089: { // GL_TEXTURE_COORD_ARRAY_TYPE
- var attribute = GLImmediate.clientAttributes[GLImmediate.TEXTURE0];
+ var attribute = GLImmediate.clientAttributes[GLImmediate.TEXTURE0 + GLImmediate.clientActiveTexture];
{{{ makeSetValue('params', '0', 'attribute ? attribute.type : 0', 'i32') }}};
return;
}
case 0x808A: { // GL_TEXTURE_COORD_ARRAY_STRIDE
- var attribute = GLImmediate.clientAttributes[GLImmediate.TEXTURE0];
+ var attribute = GLImmediate.clientAttributes[GLImmediate.TEXTURE0 + GLImmediate.clientActiveTexture];
{{{ makeSetValue('params', '0', 'attribute ? attribute.stride : 0', 'i32') }}};
return;
}
@@ -1812,7 +1812,7 @@ var LibraryGL = {
};
var glGetString = _glGetString;
- _glGetString = function(name_) {
+ _glGetString = function _glGetString(name_) {
if (GL.stringCache[name_]) return GL.stringCache[name_];
switch(name_) {
case 0x1F03 /* GL_EXTENSIONS */: // Add various extensions that we can support
@@ -1836,7 +1836,7 @@ var LibraryGL = {
GL.shaderOriginalSources = {};
#endif
var glCreateShader = _glCreateShader;
- _glCreateShader = function(shaderType) {
+ _glCreateShader = function _glCreateShader(shaderType) {
var id = glCreateShader(shaderType);
GL.shaderInfos[id] = {
type: shaderType,
@@ -1846,7 +1846,7 @@ var LibraryGL = {
};
var glShaderSource = _glShaderSource;
- _glShaderSource = function(shader, count, string, length) {
+ _glShaderSource = function _glShaderSource(shader, count, string, length) {
var source = GL.getSource(shader, count, string, length);
#if GL_DEBUG
console.log("glShaderSource: Input: \n" + source);
@@ -1959,7 +1959,7 @@ var LibraryGL = {
};
var glCompileShader = _glCompileShader;
- _glCompileShader = function(shader) {
+ _glCompileShader = function _glCompileShader(shader) {
Module.ctx.compileShader(GL.shaders[shader]);
#if GL_DEBUG
if (!Module.ctx.getShaderParameter(GL.shaders[shader], Module.ctx.COMPILE_STATUS)) {
@@ -1974,14 +1974,14 @@ var LibraryGL = {
GL.programShaders = {};
var glAttachShader = _glAttachShader;
- _glAttachShader = function(program, shader) {
+ _glAttachShader = function _glAttachShader(program, shader) {
if (!GL.programShaders[program]) GL.programShaders[program] = [];
GL.programShaders[program].push(shader);
glAttachShader(program, shader);
};
var glDetachShader = _glDetachShader;
- _glDetachShader = function(program, shader) {
+ _glDetachShader = function _glDetachShader(program, shader) {
var programShader = GL.programShaders[program];
if (!programShader) {
Module.printErr('WARNING: _glDetachShader received invalid program: ' + program);
@@ -1993,7 +1993,7 @@ var LibraryGL = {
};
var glUseProgram = _glUseProgram;
- _glUseProgram = function(program) {
+ _glUseProgram = function _glUseProgram(program) {
#if GL_DEBUG
if (GL.debug) {
Module.printErr('[using program with shaders]');
@@ -2010,7 +2010,7 @@ var LibraryGL = {
}
var glDeleteProgram = _glDeleteProgram;
- _glDeleteProgram = function(program) {
+ _glDeleteProgram = function _glDeleteProgram(program) {
glDeleteProgram(program);
if (program == GL.currProgram) GL.currProgram = 0;
};
@@ -2018,12 +2018,12 @@ var LibraryGL = {
// If attribute 0 was not bound, bind it to 0 for WebGL performance reasons. Track if 0 is free for that.
var zeroUsedPrograms = {};
var glBindAttribLocation = _glBindAttribLocation;
- _glBindAttribLocation = function(program, index, name) {
+ _glBindAttribLocation = function _glBindAttribLocation(program, index, name) {
if (index == 0) zeroUsedPrograms[program] = true;
glBindAttribLocation(program, index, name);
};
var glLinkProgram = _glLinkProgram;
- _glLinkProgram = function(program) {
+ _glLinkProgram = function _glLinkProgram(program) {
if (!(program in zeroUsedPrograms)) {
Module.ctx.bindAttribLocation(GL.programs[program], 0, 'a_position');
}
@@ -2031,7 +2031,7 @@ var LibraryGL = {
};
var glBindBuffer = _glBindBuffer;
- _glBindBuffer = function(target, buffer) {
+ _glBindBuffer = function _glBindBuffer(target, buffer) {
glBindBuffer(target, buffer);
if (target == Module.ctx.ARRAY_BUFFER) {
if (GLEmulation.currentVao) {
@@ -2046,7 +2046,7 @@ var LibraryGL = {
};
var glGetFloatv = _glGetFloatv;
- _glGetFloatv = function(pname, params) {
+ _glGetFloatv = function _glGetFloatv(pname, params) {
if (pname == 0x0BA6) { // GL_MODELVIEW_MATRIX
HEAPF32.set(GL.immediate.matrix['m'], params >> 2);
} else if (pname == 0x0BA7) { // GL_PROJECTION_MATRIX
@@ -2069,7 +2069,7 @@ var LibraryGL = {
};
var glHint = _glHint;
- _glHint = function(target, mode) {
+ _glHint = function _glHint(target, mode) {
if (target == 0x84EF) { // GL_TEXTURE_COMPRESSION_HINT
return;
}
@@ -2077,21 +2077,21 @@ var LibraryGL = {
};
var glEnableVertexAttribArray = _glEnableVertexAttribArray;
- _glEnableVertexAttribArray = function(index) {
+ _glEnableVertexAttribArray = function _glEnableVertexAttribArray(index) {
glEnableVertexAttribArray(index);
GLEmulation.enabledVertexAttribArrays[index] = 1;
if (GLEmulation.currentVao) GLEmulation.currentVao.enabledVertexAttribArrays[index] = 1;
};
var glDisableVertexAttribArray = _glDisableVertexAttribArray;
- _glDisableVertexAttribArray = function(index) {
+ _glDisableVertexAttribArray = function _glDisableVertexAttribArray(index) {
glDisableVertexAttribArray(index);
delete GLEmulation.enabledVertexAttribArrays[index];
if (GLEmulation.currentVao) delete GLEmulation.currentVao.enabledVertexAttribArrays[index];
};
var glVertexAttribPointer = _glVertexAttribPointer;
- _glVertexAttribPointer = function(index, size, type, normalized, stride, pointer) {
+ _glVertexAttribPointer = function _glVertexAttribPointer(index, size, type, normalized, stride, pointer) {
glVertexAttribPointer(index, size, type, normalized, stride, pointer);
if (GLEmulation.currentVao) { // TODO: avoid object creation here? likely not hot though
GLEmulation.currentVao.vertexAttribPointers[index] = [index, size, type, normalized, stride, pointer];
@@ -2190,7 +2190,7 @@ var LibraryGL = {
case 0x8090: // GL_COLOR_ARRAY_POINTER
attribute = GLImmediate.clientAttributes[GLImmediate.COLOR]; break;
case 0x8092: // GL_TEXTURE_COORD_ARRAY_POINTER
- attribute = GLImmediate.clientAttributes[GLImmediate.TEXTURE0]; break;
+ attribute = GLImmediate.clientAttributes[GLImmediate.TEXTURE0 + GLImmediate.clientActiveTexture]; break;
default: throw 'TODO: glGetPointerv for ' + name;
}
{{{ makeSetValue('p', '0', 'attribute ? attribute.pointer : 0', 'i32') }}};
@@ -2212,14 +2212,14 @@ var LibraryGL = {
function CNaiveListMap() {
var list = [];
- this.insert = function(key, val) {
+ this.insert = function CNaiveListMap_insert(key, val) {
if (this.contains(key|0)) return false;
list.push([key, val]);
return true;
};
var __contains_i;
- this.contains = function(key) {
+ this.contains = function CNaiveListMap_contains(key) {
for (__contains_i = 0; __contains_i < list.length; ++__contains_i) {
if (list[__contains_i][0] === key) return true;
}
@@ -2227,7 +2227,7 @@ var LibraryGL = {
};
var __get_i;
- this.get = function(key) {
+ this.get = function CNaiveListMap_get(key) {
for (__get_i = 0; __get_i < list.length; ++__get_i) {
if (list[__get_i][0] === key) return list[__get_i][1];
}
@@ -2261,7 +2261,7 @@ var LibraryGL = {
function CNLNode() {
var map = new CNaiveListMap();
- this.child = function(keyFrag) {
+ this.child = function CNLNode_child(keyFrag) {
if (!map.contains(keyFrag|0)) {
map.insert(keyFrag|0, new CNLNode());
}
@@ -2269,11 +2269,11 @@ var LibraryGL = {
};
this.value = undefined;
- this.get = function() {
+ this.get = function CNLNode_get() {
return this.value;
};
- this.set = function(val) {
+ this.set = function CNLNode_set(val) {
this.value = val;
};
}
@@ -2281,22 +2281,22 @@ var LibraryGL = {
function CKeyView(root) {
var cur;
- this.reset = function() {
+ this.reset = function CKeyView_reset() {
cur = root;
return this;
};
this.reset();
- this.next = function(keyFrag) {
+ this.next = function CKeyView_next(keyFrag) {
cur = cur.child(keyFrag);
return this;
};
- this.get = function() {
+ this.get = function CKeyView_get() {
return cur.get();
};
- this.set = function(val) {
+ this.set = function CKeyView_set(val) {
cur.set(val);
};
};
@@ -2304,17 +2304,17 @@ var LibraryGL = {
var root;
var staticKeyView;
- this.createKeyView = function() {
+ this.createKeyView = function CNLNode_createKeyView() {
return new CKeyView(root);
}
- this.clear = function() {
+ this.clear = function CNLNode_clear() {
root = new CNLNode();
staticKeyView = this.createKeyView();
};
this.clear();
- this.getStaticKeyView = function() {
+ this.getStaticKeyView = function CNLNode_getStaticKeyView() {
staticKeyView.reset();
return staticKeyView;
};
@@ -2548,7 +2548,7 @@ var LibraryGL = {
GL_SRC_ALPHA
];
- this.traverseState = function(keyView) {
+ this.traverseState = function CTexEnv_traverseState(keyView) {
keyView.next(this.mode);
keyView.next(this.colorCombiner);
keyView.next(this.alphaCombiner);
@@ -2584,7 +2584,7 @@ var LibraryGL = {
this.enabled_tex3D = false;
this.enabled_texCube = false;
- this.traverseState = function(keyView) {
+ this.traverseState = function CTexUnit_traverseState(keyView) {
var texUnitType = this.getTexType();
keyView.next(texUnitType);
if (!texUnitType) return;
@@ -2593,11 +2593,11 @@ var LibraryGL = {
};
// Class impls:
- CTexUnit.prototype.enabled = function() {
+ CTexUnit.prototype.enabled = function CTexUnit_enabled() {
return this.getTexType() != 0;
}
- CTexUnit.prototype.genPassLines = function(passOutputVar, passInputVar, texUnitID) {
+ CTexUnit.prototype.genPassLines = function CTexUnit_genPassLines(passOutputVar, passInputVar, texUnitID) {
if (!this.enabled()) {
return ["vec4 " + passOutputVar + " = " + passInputVar + ";"];
}
@@ -2605,7 +2605,7 @@ var LibraryGL = {
return this.env.genPassLines(passOutputVar, passInputVar, texUnitID);
}
- CTexUnit.prototype.getTexType = function() {
+ CTexUnit.prototype.getTexType = function CTexUnit_getTexType() {
if (this.enabled_texCube) {
return GL_TEXTURE_CUBE_MAP;
} else if (this.enabled_tex3D) {
@@ -2618,7 +2618,7 @@ var LibraryGL = {
return 0;
}
- CTexEnv.prototype.genPassLines = function(passOutputVar, passInputVar, texUnitID) {
+ CTexEnv.prototype.genPassLines = function CTexEnv_genPassLines(passOutputVar, passInputVar, texUnitID) {
switch (this.mode) {
case GL_REPLACE: {
/* RGB:
@@ -2740,9 +2740,9 @@ var LibraryGL = {
return Abort_NoSupport("Unsupported TexEnv mode: 0x" + this.mode.toString(16));
}
- CTexEnv.prototype.genCombinerLines = function(isColor, outputVar,
- passInputVar, texUnitID,
- combiner, srcArr, opArr)
+ CTexEnv.prototype.genCombinerLines = function CTexEnv_getCombinerLines(isColor, outputVar,
+ passInputVar, texUnitID,
+ combiner, srcArr, opArr)
{
var argsNeeded = null;
switch (combiner) {
@@ -3227,7 +3227,9 @@ var LibraryGL = {
#if ASSERTIONS
if (!useCurrProgram) {
- assert(GL.immediate.TexEnvJIT.getTexUnitType(i) != 0, "GL_TEXTURE" + i + " coords are supplied, but that texture unit is disabled in the fixed-function pipeline.");
+ if (GL.immediate.TexEnvJIT.getTexUnitType(i) == 0) {
+ Runtime.warnOnce("GL_TEXTURE" + i + " coords are supplied, but that texture unit is disabled in the fixed-function pipeline.");
+ }
}
#endif
@@ -3596,7 +3598,7 @@ var LibraryGL = {
// Replace some functions with immediate-mode aware versions. If there are no client
// attributes enabled, and we use webgl-friendly modes (no GL_QUADS), then no need
// for emulation
- _glDrawArrays = function(mode, first, count) {
+ _glDrawArrays = function _glDrawArrays(mode, first, count) {
if (GL.immediate.totalEnabledClientAttributes == 0 && mode <= 6) {
Module.ctx.drawArrays(mode, first, count);
return;
@@ -3612,7 +3614,7 @@ var LibraryGL = {
GL.immediate.mode = -1;
};
- _glDrawElements = function(mode, count, type, indices, start, end) { // start, end are given if we come from glDrawRangeElements
+ _glDrawElements = function _glDrawElements(mode, count, type, indices, start, end) { // start, end are given if we come from glDrawRangeElements
if (GL.immediate.totalEnabledClientAttributes == 0 && mode <= 6 && GL.currElementArrayBuffer) {
Module.ctx.drawElements(mode, count, type, indices);
return;
@@ -3652,43 +3654,43 @@ var LibraryGL = {
}
var glActiveTexture = _glActiveTexture;
- _glActiveTexture = function(texture) {
+ _glActiveTexture = function _glActiveTexture(texture) {
GL.immediate.TexEnvJIT.hook_activeTexture(texture);
glActiveTexture(texture);
};
var glEnable = _glEnable;
- _glEnable = function(cap) {
+ _glEnable = function _glEnable(cap) {
GL.immediate.TexEnvJIT.hook_enable(cap);
glEnable(cap);
};
var glDisable = _glDisable;
- _glDisable = function(cap) {
+ _glDisable = function _glDisable(cap) {
GL.immediate.TexEnvJIT.hook_disable(cap);
glDisable(cap);
};
var glTexEnvf = (typeof(_glTexEnvf) != 'undefined') ? _glTexEnvf : function(){};
- _glTexEnvf = function(target, pname, param) {
+ _glTexEnvf = function _glTexEnvf(target, pname, param) {
GL.immediate.TexEnvJIT.hook_texEnvf(target, pname, param);
// Don't call old func, since we are the implementor.
//glTexEnvf(target, pname, param);
};
var glTexEnvi = (typeof(_glTexEnvi) != 'undefined') ? _glTexEnvi : function(){};
- _glTexEnvi = function(target, pname, param) {
+ _glTexEnvi = function _glTexEnvi(target, pname, param) {
GL.immediate.TexEnvJIT.hook_texEnvi(target, pname, param);
// Don't call old func, since we are the implementor.
//glTexEnvi(target, pname, param);
};
var glTexEnvfv = (typeof(_glTexEnvfv) != 'undefined') ? _glTexEnvfv : function(){};
- _glTexEnvfv = function(target, pname, param) {
+ _glTexEnvfv = function _glTexEnvfv(target, pname, param) {
GL.immediate.TexEnvJIT.hook_texEnvfv(target, pname, param);
// Don't call old func, since we are the implementor.
//glTexEnvfv(target, pname, param);
};
var glGetIntegerv = _glGetIntegerv;
- _glGetIntegerv = function(pname, params) {
+ _glGetIntegerv = function _glGetIntegerv(pname, params) {
switch (pname) {
case 0x8B8D: { // GL_CURRENT_PROGRAM
// Just query directly so we're working with WebGL objects.
@@ -4731,7 +4733,7 @@ LibraryGL.emscripten_GetProcAddress__deps = [function() {
tableImpl += '}\nreturn 0;';
LibraryManager.library.emscripten_procAddressTable = new Function('name', tableImpl);
}, 'emscripten_procAddressTable'];
-LibraryGL.emscripten_GetProcAddress = function(name) {
+LibraryGL.emscripten_GetProcAddress = function _LibraryGL_emscripten_GetProcAddress(name) {
name = name.replace('EXT', '').replace('ARB', '');
switch(name) { // misc renamings
case 'glCreateProgramObject': name = 'glCreateProgram'; break;
diff --git a/src/library_glut.js b/src/library_glut.js
index fefe7bd3..5e303fd2 100644
--- a/src/library_glut.js
+++ b/src/library_glut.js
@@ -372,7 +372,7 @@ var LibraryGLUT = {
},
glutIdleFunc: function(func) {
- var callback = function() {
+ function callback() {
if (GLUT.idleFunc) {
Runtime.dynCall('v', GLUT.idleFunc);
Browser.safeSetTimeout(callback, 0);
diff --git a/src/library_idbfs.js b/src/library_idbfs.js
index ab55673f..7f50f17e 100644
--- a/src/library_idbfs.js
+++ b/src/library_idbfs.js
@@ -58,7 +58,7 @@ mergeInto(LibraryManager.library, {
}
var completed = 0;
- var done = function(err) {
+ function done(err) {
if (err) return callback(err);
if (++completed >= total) {
return callback(null);
@@ -68,7 +68,7 @@ mergeInto(LibraryManager.library, {
// create a single transaction to handle and IDB reads / writes we'll need to do
var db = src.type === 'remote' ? src.db : dst.db;
var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readwrite');
- transaction.onerror = function() { callback(this.error); };
+ transaction.onerror = function transaction_onerror() { callback(this.error); };
var store = transaction.objectStore(IDBFS.DB_STORE_NAME);
for (var path in create) {
@@ -92,8 +92,8 @@ mergeInto(LibraryManager.library, {
} else {
// save file to IDB
var req = store.put(entry, path);
- req.onsuccess = function() { done(null); };
- req.onerror = function() { done(this.error); };
+ req.onsuccess = function req_onsuccess() { done(null); };
+ req.onerror = function req_onerror() { done(this.error); };
}
}
@@ -117,18 +117,18 @@ mergeInto(LibraryManager.library, {
} else {
// delete file from IDB
var req = store.delete(path);
- req.onsuccess = function() { done(null); };
- req.onerror = function() { done(this.error); };
+ req.onsuccess = function req_onsuccess() { done(null); };
+ req.onerror = function req_onerror() { done(this.error); };
}
}
},
getLocalSet: function(mount, callback) {
var files = {};
- var isRealDir = function(p) {
+ function isRealDir(p) {
return p !== '.' && p !== '..';
};
- var toAbsolute = function(root) {
+ function toAbsolute(root) {
return function(p) {
return PATH.join2(root, p);
}
@@ -177,17 +177,17 @@ mergeInto(LibraryManager.library, {
} catch (e) {
return onerror(e);
}
- req.onupgradeneeded = function() {
+ req.onupgradeneeded = function req_onupgradeneeded() {
db = req.result;
db.createObjectStore(IDBFS.DB_STORE_NAME);
};
- req.onsuccess = function() {
+ req.onsuccess = function req_onsuccess() {
db = req.result;
// add to the cache
IDBFS.dbs[name] = db;
callback(null, db);
};
- req.onerror = function() {
+ req.onerror = function req_onerror() {
callback(this.error);
};
},
@@ -198,10 +198,10 @@ mergeInto(LibraryManager.library, {
if (err) return callback(err);
var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readonly');
- transaction.onerror = function() { callback(this.error); };
+ transaction.onerror = function transaction_onerror() { callback(this.error); };
var store = transaction.objectStore(IDBFS.DB_STORE_NAME);
- store.openCursor().onsuccess = function(event) {
+ store.openCursor().onsuccess = function store_openCursor_onsuccess(event) {
var cursor = event.target.result;
if (!cursor) {
return callback(null, { type: 'remote', db: db, files: files });
diff --git a/src/library_memfs.js b/src/library_memfs.js
index 9f528108..d3148d8b 100644
--- a/src/library_memfs.js
+++ b/src/library_memfs.js
@@ -225,9 +225,9 @@ mergeInto(LibraryManager.library, {
#if ASSERTIONS
assert(buffer.length);
#endif
- if (canOwn && buffer.buffer === HEAP8.buffer && offset === 0) {
- node.contents = buffer; // this is a subarray of the heap, and we can own it
- node.contentMode = MEMFS.CONTENT_OWNING;
+ if (canOwn && offset === 0) {
+ node.contents = buffer; // this could be a subarray of Emscripten HEAP, or allocated from some other source.
+ node.contentMode = (buffer.buffer === HEAP8.buffer) ? MEMFS.CONTENT_OWNING : MEMFS.CONTENT_FIXED;
} else {
node.contents = new Uint8Array(buffer.subarray(offset, offset+length));
node.contentMode = MEMFS.CONTENT_FIXED;
diff --git a/src/library_sdl.js b/src/library_sdl.js
index 024f0c35..5b43b7ab 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -153,24 +153,30 @@ var LibrarySDL = {
120: 27,
121: 28,
122: 29, // Z
- 44: 54, // comma
- 46: 55, // period
- 47: 56, // slash
- 49: 30, // 1
- 50: 31,
- 51: 32,
- 52: 33,
- 53: 34,
- 54: 35,
- 55: 36,
- 56: 37,
- 57: 38, // 9
- 48: 39, // 0
- 13: 40, // return
- 9: 43, // tab
- 27: 41, // escape
- 32: 44, // space
- 92: 49, // backslash
+ 49: 30, // 1
+ 50: 31,
+ 51: 32,
+ 52: 33,
+ 53: 34,
+ 54: 35,
+ 55: 36,
+ 56: 37,
+ 57: 38, // 9
+ 48: 39, // 0
+ 13: 40, // return
+ 27: 41, // escape
+ 8: 42, // backspace
+ 9: 43, // tab
+ 32: 44, // space
+ 61: 46, // equals
+ 91: 47, // left bracket
+ 93: 48, // right bracket
+ 92: 49, // backslash
+ 59: 51, // ;
+ 96: 52, // apostrophe
+ 44: 54, // comma
+ 46: 55, // period
+ 47: 56, // slash
305: 224, // ctrl
308: 226, // alt
},
@@ -1295,12 +1301,12 @@ var LibrarySDL = {
IMG_Load_RW: function(rwopsID, freeSrc) {
try {
// stb_image integration support
- var cleanup = function() {
+ function cleanup() {
if (rwops && freeSrc) _SDL_FreeRW(rwopsID);
};
function addCleanup(func) {
var old = cleanup;
- cleanup = function() {
+ cleanup = function added_cleanup() {
old();
func();
}
@@ -1475,7 +1481,7 @@ var LibrarySDL = {
SDL.audio.buffer = _malloc(SDL.audio.bufferSize);
// Create a callback function that will be routinely called to ask more audio data from the user application.
- SDL.audio.caller = function() {
+ SDL.audio.caller = function SDL_audio_caller() {
if (!SDL.audio) {
return;
}
@@ -1489,7 +1495,7 @@ var LibrarySDL = {
SDL.audio.audioOutput['mozSetup'](SDL.audio.channels, SDL.audio.freq); // use string attributes on mozOutput for closure compiler
SDL.audio.mozBuffer = new Float32Array(totalSamples);
SDL.audio.nextPlayTime = 0;
- SDL.audio.pushAudio = function(ptr, size) {
+ SDL.audio.pushAudio = function SDL_audio_pushAudio(ptr, size) {
var mozBuffer = SDL.audio.mozBuffer;
// The input audio data for SDL audio is either 8-bit or 16-bit interleaved across channels, output for Mozilla Audio Data API
// needs to be Float32 interleaved, so perform a sample conversion.
@@ -1856,7 +1862,7 @@ var LibrarySDL = {
audio.frequency = info.audio.frequency;
// TODO: handle N loops. Behavior matches Mix_PlayMusic
audio.loop = loops != 0;
- audio['onended'] = function() { // TODO: cache these
+ audio['onended'] = function SDL_audio_onended() { // TODO: cache these
channelInfo.audio = null;
if (SDL.channelFinished) {
Runtime.getFuncWrapper(SDL.channelFinished, 'vi')(channel);
@@ -1883,7 +1889,7 @@ var LibrarySDL = {
source.loop = false;
source.buffer = context.createBuffer(numChannels, 1, audio.frequency);
var jsNode = context.createJavaScriptNode(2048, numChannels, numChannels);
- jsNode.onaudioprocess = function(event) {
+ jsNode.onaudioprocess = function jsNode_onaudioprocess(event) {
var buffers = new Array(numChannels);
for (var i = 0; i < numChannels; ++i) {
buffers[i] = event.outputBuffer.getChannelData(i);
diff --git a/src/library_sockfs.js b/src/library_sockfs.js
index af29d11b..bc3aa997 100644
--- a/src/library_sockfs.js
+++ b/src/library_sockfs.js
@@ -138,7 +138,9 @@ mergeInto(LibraryManager.library, {
console.log('connect: ' + url);
#endif
// the node ws library API is slightly different than the browser's
- var opts = ENVIRONMENT_IS_NODE ? {} : ['binary'];
+ var opts = ENVIRONMENT_IS_NODE ? {headers: {'websocket-protocol': ['binary']}} : ['binary'];
+ // If node we use the ws library.
+ var WebSocket = ENVIRONMENT_IS_NODE ? require('ws') : window['WebSocket'];
ws = new WebSocket(url, opts);
ws.binaryType = 'arraybuffer';
} catch (e) {
@@ -208,7 +210,7 @@ mergeInto(LibraryManager.library, {
}
};
- var handleMessage = function(data) {
+ function handleMessage(data) {
assert(typeof data !== 'string' && data.byteLength !== undefined); // must receive an ArrayBuffer
data = new Uint8Array(data); // make a typed array view on the array buffer
@@ -247,7 +249,7 @@ mergeInto(LibraryManager.library, {
});
} else {
peer.socket.onopen = handleOpen;
- peer.socket.onmessage = function(event) {
+ peer.socket.onmessage = function peer_socket_onmessage(event) {
handleMessage(event.data);
};
}
@@ -573,4 +575,4 @@ mergeInto(LibraryManager.library, {
}
}
}
-}); \ No newline at end of file
+});
diff --git a/src/parseTools.js b/src/parseTools.js
index 16f4058c..c4f28184 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -157,6 +157,10 @@ function isStructType(type) {
return type[0] == '%';
}
+function isVectorType(type) {
+ return type[type.length-1] === '>';
+}
+
function isStructuralType(type) {
return /^{ ?[^}]* ?}$/.test(type); // { i32, i8 } etc. - anonymous struct types
}
@@ -215,8 +219,22 @@ function isIdenticallyImplemented(type1, type2) {
}
function isIllegalType(type) {
- var bits = getBits(type);
- return bits > 0 && (bits >= 64 || !isPowerOfTwo(bits));
+ switch (type) {
+ case 'i1':
+ case 'i8':
+ case 'i16':
+ case 'i32':
+ case 'float':
+ case 'double':
+ case 'rawJS':
+ case '<2 x float>':
+ case '<4 x float>':
+ case '<2 x i32>':
+ case '<4 x i32>':
+ case 'void': return false;
+ }
+ if (!type || type[type.length-1] === '*') return false;
+ return true;
}
function isVoidType(type) {
@@ -287,6 +305,9 @@ function getReturnType(type) {
if (pointingLevels(type) > 1) return '*'; // the type of a call can be either the return value, or the entire function. ** or more means it is a return value
var lastOpen = type.lastIndexOf('(');
if (lastOpen > 0) {
+ // handle things like void (i32)* (i32, void (i32)*)*
+ var closeStar = type.indexOf(')*');
+ if (closeStar > 0 && closeStar < type.length-2) lastOpen = closeStar+3;
return type.substr(0, lastOpen-1);
}
return type;
@@ -466,26 +487,13 @@ function parseParamTokens(params) {
Types.needAnalysis[ret[ret.length-1].type] = 0;
anonymousIndex ++;
}
- } else if (segment[1].text in PARSABLE_LLVM_FUNCTIONS) {
- ret.push(parseLLVMFunctionCall(segment));
- } else if (segment[1].text === 'blockaddress') {
- ret.push(parseBlockAddress(segment));
- } else if (segment[1].type && segment[1].type == '{') {
- ret.push(parseLLVMSegment(segment));
} else {
if (segment[2] && segment[2].text == 'to') { // part of bitcast params
segment = segment.slice(0, 2);
}
- while (segment.length > 2) {
- segment[0].text += segment[1].text;
- segment.splice(1, 1); // TODO: merge tokens nicely
- }
- ret.push({
- intertype: 'value',
- type: segment[0].text,
- ident: toNiceIdent(parseNumerical(segment[1].text, segment[0].text))
- });
- Types.needAnalysis[removeAllPointing(ret[ret.length-1].type)] = 0;
+ var parsed = parseLLVMSegment(segment);
+ if (parsed.intertype === 'value' && !isIllegalType(parsed.type)) parsed.ident = parseNumerical(parsed.ident, parsed.type);
+ ret.push(parsed);
}
ret[ret.length-1].byVal = byVal;
}
@@ -559,25 +567,6 @@ function sortGlobals(globals) {
});
}
-function finalizeParam(param) {
- if (param.intertype in PARSABLE_LLVM_FUNCTIONS) {
- return finalizeLLVMFunctionCall(param);
- } else if (param.intertype === 'blockaddress') {
- return finalizeBlockAddress(param);
- } else if (param.intertype === 'jsvalue') {
- return param.ident;
- } else {
- if (param.type == 'i64' && USE_TYPED_ARRAYS == 2) {
- return parseI64Constant(param.ident);
- }
- var ret = toNiceIdent(param.ident);
- if (ret in Variables.globals) {
- ret = makeGlobalUse(ret);
- }
- return ret;
- }
-}
-
// Segment ==> Parameter
function parseLLVMSegment(segment) {
var type;
@@ -2001,6 +1990,8 @@ function finalizeLLVMParameter(param, noIndexizeFunctions) {
} else if (param.ident == 'zeroinitializer') {
if (isStructType(param.type)) {
return makeLLVMStruct(zeros(Types.types[param.type].fields.length));
+ } else if (isVectorType(param.type)) {
+ return ensureVector(0, getVectorBaseType(param.type));
} else {
return '0';
}
@@ -2023,7 +2014,7 @@ function finalizeLLVMParameter(param, noIndexizeFunctions) {
} else if (param.intertype == 'mathop') {
return processMathop(param);
} else if (param.intertype === 'vector') {
- return 'float32x4(' + param.idents.join(',') + ')';
+ return getVectorBaseType(param.type) + '32x4(' + param.idents.join(',') + ')';
} else {
throw 'invalid llvm parameter: ' + param.intertype;
}
@@ -2286,7 +2277,7 @@ function processMathop(item) {
case 'trunc': {
return '((' + idents[0] + '[0]) & ' + (Math.pow(2, bitsLeft)-1) + ')';
}
- case 'select': return idents[0] + ' ? ' + makeCopyI64(idents[1]) + ' : ' + makeCopyI64(idents[2]);
+ case 'select': return '(' + idents[0] + ' ? ' + makeCopyI64(idents[1]) + ' : ' + makeCopyI64(idents[2]) + ')';;
case 'ptrtoint': return makeI64(idents[0], 0);
case 'inttoptr': {
var m = /\(?\[(\d+),\d+\]\)?/.exec(idents[0]);
@@ -2383,6 +2374,9 @@ function processMathop(item) {
return 'SIMD.uint32x4BitsToFloat32x4(' + idents[0] + ')';
}
}
+ case 'and': return 'SIMD.and(' + idents[0] + ',' + idents[1] + ')';
+ case 'or': return 'SIMD.or(' + idents[0] + ',' + idents[1] + ')';
+ case 'xor': return 'SIMD.xor(' + idents[0] + ',' + idents[1] + ')';
default: throw 'vector op todo: ' + dump(item);
}
}
@@ -2487,7 +2481,7 @@ function processMathop(item) {
}
case 'fpext': case 'sext': return idents[0];
case 'fptrunc': return idents[0];
- case 'select': return idents[0] + '?' + asmEnsureFloat(idents[1], item.type) + ':' + asmEnsureFloat(idents[2], item.type);
+ case 'select': return '(' + idents[0] + '?' + asmEnsureFloat(idents[1], item.type) + ':' + asmEnsureFloat(idents[2], item.type) + ')';
case 'ptrtoint': case 'inttoptr': {
var ret = '';
if (QUANTUM_SIZE == 1) {
diff --git a/src/preamble.js b/src/preamble.js
index 9e72e7b8..c88e4052 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -1060,7 +1060,7 @@ Module['writeAsciiToMemory'] = writeAsciiToMemory;
{{{ reSign }}}
#if PRECISE_I32_MUL
-if (!Math['imul']) Math['imul'] = function(a, b) {
+if (!Math['imul']) Math['imul'] = function imul(a, b) {
var ah = a >>> 16;
var al = a & 0xffff;
var bh = b >>> 16;
@@ -1068,14 +1068,14 @@ if (!Math['imul']) Math['imul'] = function(a, b) {
return (al*bl + ((ah*bl + al*bh) << 16))|0;
};
#else
-Math['imul'] = function(a, b) {
+Math['imul'] = function imul(a, b) {
return (a*b)|0; // fast but imprecise
};
#endif
Math.imul = Math['imul'];
#if TO_FLOAT32
-if (!Math['toFloat32']) Math['toFloat32'] = function(x) {
+if (!Math['toFloat32']) Math['toFloat32'] = function toFloat32(x) {
return x;
};
Math.toFloat32 = Math['toFloat32'];
diff --git a/src/proxyClient.js b/src/proxyClient.js
index 38ea5771..8f4ad7a6 100644
--- a/src/proxyClient.js
+++ b/src/proxyClient.js
@@ -5,7 +5,7 @@ Module.ctx = Module.canvas.getContext('2d');
var worker = new Worker('{{{ filename }}}.js');
-worker.onmessage = function(event) {
+worker.onmessage = function worker_onmessage(event) {
var data = event.data;
switch (data.target) {
case 'stdout': {
diff --git a/src/proxyWorker.js b/src/proxyWorker.js
index 29b2528d..5d34b900 100644
--- a/src/proxyWorker.js
+++ b/src/proxyWorker.js
@@ -2,12 +2,12 @@
function EventListener() {
this.listeners = {};
- this.addEventListener = function(event, func) {
+ this.addEventListener = function addEventListener(event, func) {
if (!this.listeners[event]) this.listeners[event] = [];
this.listeners[event].push(func);
};
- this.fireEvent = function(event) {
+ this.fireEvent = function fireEvent(event) {
event.preventDefault = function(){};
if (event.type in this.listeners) {
@@ -22,17 +22,17 @@ var window = this;
var windowExtra = new EventListener();
for (var x in windowExtra) window[x] = windowExtra[x];
-window.close = function() {
+window.close = function window_close() {
postMessage({ target: 'window', method: 'close' });
};
var document = new EventListener();
-document.createElement = function(what) {
+document.createElement = function document_createElement(what) {
switch(what) {
case 'canvas': {
var canvas = new EventListener();
- canvas.ensureData = function() {
+ canvas.ensureData = function canvas_ensureData() {
if (!canvas.data || canvas.data.width !== canvas.width || canvas.data.height !== canvas.height) {
canvas.data = {
width: canvas.width,
@@ -42,7 +42,7 @@ document.createElement = function(what) {
postMessage({ target: 'canvas', op: 'resize', width: canvas.width, height: canvas.height });
}
};
- canvas.getContext = function(type) {
+ canvas.getContext = function canvas_getContext(type) {
assert(type == '2d');
return {
getImageData: function(x, y, w, h) {
@@ -63,7 +63,7 @@ document.createElement = function(what) {
};
};
canvas.boundingClientRect = {};
- canvas.getBoundingClientRect = function() {
+ canvas.getBoundingClientRect = function canvas_getBoundingClientRect() {
return {
width: canvas.boundingClientRect.width,
height: canvas.boundingClientRect.height,
@@ -89,10 +89,10 @@ Module.canvas = document.createElement('canvas');
Module.setStatus = function(){};
-Module.print = function(x) {
+Module.print = function Module_print(x) {
postMessage({ target: 'stdout', content: x });
};
-Module.printErr = function(x) {
+Module.printErr = function Module_printErr(x) {
postMessage({ target: 'stderr', content: x });
};
@@ -112,7 +112,7 @@ function messageResender() {
}
}
-onmessage = function(message) {
+onmessage = function onmessage(message) {
if (!calledMain) {
if (!messageBuffer) {
messageBuffer = [];
diff --git a/src/runtime.js b/src/runtime.js
index ca2304da..3f89dc84 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -394,7 +394,7 @@ var Runtime = {
getFuncWrapper: function(func, sig) {
assert(sig);
if (!Runtime.funcWrappers[func]) {
- Runtime.funcWrappers[func] = function() {
+ Runtime.funcWrappers[func] = function dynCall_wrapper() {
return Runtime.dynCall(sig, func, arguments);
};
}
@@ -452,7 +452,7 @@ var Runtime = {
buffer.length = 0;
return ret;
}
- this.processJSString = function(string) {
+ this.processJSString = function processJSString(string) {
string = unescape(encodeURIComponent(string));
var ret = [];
for (var i = 0; i < string.length; i++) {
diff --git a/src/settings.js b/src/settings.js
index d2b47dc8..42e31b3a 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -410,7 +410,8 @@ var HEADLESS = 0; // If 1, will include shim code that tries to 'fake' a browser
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.
-var ASM_JS = 0; // If 1, generate code in asm.js format.
+var ASM_JS = 0; // If 1, generate code in asm.js format. If 2, emits the same code except
+ // for omitting 'use asm'
var PGO = 0; // Enables profile-guided optimization in the form of runtime checks for
// which functions are actually called. Emits a list during shutdown that you
diff --git a/src/shell.js b/src/shell.js
index be23b3c1..b68e16d9 100644
--- a/src/shell.js
+++ b/src/shell.js
@@ -38,17 +38,17 @@ var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIR
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
- Module['print'] = function(x) {
+ Module['print'] = function print(x) {
process['stdout'].write(x + '\n');
};
- Module['printErr'] = function(x) {
+ Module['printErr'] = function printErr(x) {
process['stderr'].write(x + '\n');
};
var nodeFS = require('fs');
var nodePath = require('path');
- Module['read'] = function(filename, binary) {
+ Module['read'] = function read(filename, binary) {
filename = nodePath['normalize'](filename);
var ret = nodeFS['readFileSync'](filename);
// The path is absolute if the normalized version is the same as the resolved.
@@ -60,9 +60,9 @@ if (ENVIRONMENT_IS_NODE) {
return ret;
};
- Module['readBinary'] = function(filename) { return Module['read'](filename, true) };
+ Module['readBinary'] = function readBinary(filename) { return Module['read'](filename, true) };
- Module['load'] = function(f) {
+ Module['load'] = function load(f) {
globalEval(read(f));
};
@@ -77,10 +77,10 @@ else if (ENVIRONMENT_IS_SHELL) {
if (typeof read != 'undefined') {
Module['read'] = read;
} else {
- Module['read'] = function() { throw 'no read() available (jsc?)' };
+ Module['read'] = function read() { throw 'no read() available (jsc?)' };
}
- Module['readBinary'] = function(f) {
+ Module['readBinary'] = function readBinary(f) {
return read(f, 'binary');
};
@@ -93,7 +93,7 @@ else if (ENVIRONMENT_IS_SHELL) {
this['{{{ EXPORT_NAME }}}'] = Module;
}
else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
- Module['read'] = function(url) {
+ Module['read'] = function read(url) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, false);
xhr.send(null);
@@ -105,10 +105,10 @@ else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
}
if (typeof console !== 'undefined') {
- Module['print'] = function(x) {
+ Module['print'] = function print(x) {
console.log(x);
};
- Module['printErr'] = function(x) {
+ Module['printErr'] = function printErr(x) {
console.log(x);
};
} else {
@@ -136,7 +136,7 @@ function globalEval(x) {
eval.call(null, x);
}
if (!Module['load'] == 'undefined' && Module['read']) {
- Module['load'] = function(f) {
+ Module['load'] = function load(f) {
globalEval(Module['read'](f));
};
}
diff --git a/system/include/emscripten/vector.h b/system/include/emscripten/vector.h
index ea148f0d..938f2369 100644
--- a/system/include/emscripten/vector.h
+++ b/system/include/emscripten/vector.h
@@ -4,3 +4,13 @@
typedef float float32x4 __attribute__((__vector_size__(16)));
typedef unsigned int uint32x4 __attribute__((__vector_size__(16)));
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+unsigned int emscripten_float32x4_signmask(float32x4 x);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/tests/cases/caall.ll b/tests/cases/caall.ll
index 313116e6..5b8f7f29 100644
--- a/tests/cases/caall.ll
+++ b/tests/cases/caall.ll
@@ -18,7 +18,7 @@ entry:
define (i32*)** @_ZNSt3__13mapINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPFvP6ObjectENS_4lessIS6_EENS4_INS_4pairIKS6_SA_EEEEEixERSE_(i32 %x) {
entry:
%ret = inttoptr i32 0 to (i32*)**
- ret %ret
+ ret (i32*)** %ret
}
; [#uses=1]
diff --git a/tests/cases/selectadd.ll b/tests/cases/selectadd.ll
new file mode 100644
index 00000000..093032b8
--- /dev/null
+++ b/tests/cases/selectadd.ll
@@ -0,0 +1,29 @@
+
+; ModuleID = 'tests/hello_world.bc'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*]
+
+; [#uses=0]
+define i32 @main() {
+entry:
+ br label %zero
+
+zero:
+ %.3.ph.i757 = phi i8* [ getelementptr ([15 x i8]* @.str, i32 0, i32 add (i32 xor (i32 ptrtoint (i8* getelementptr ([15 x i8]* @.str, i32 0, i32 select (i1 icmp ugt (i32 sub (i32 0, i32 add (i32 ptrtoint ([15 x i8]* @.str to i32), i32 25)), i32 xor (i32 ptrtoint ([15 x i8]* @.str to i32), i32 -1)), i32 sub (i32 0, i32 add (i32 ptrtoint ([15 x i8]* @.str to i32), i32 25)), i32 xor (i32 ptrtoint ([15 x i8]* @.str to i32), i32 -1))) to i32), i32 -1), i32 25)), %entry ], [ getelementptr ([15 x i8]* @.str, i32 0, i32 ptrtoint (i8* getelementptr ([15 x i8]* @.str, i32 0, i32 add (i32 sub (i32 0, i32 ptrtoint ([15 x i8]* @.str to i32)), i32 25)) to i32)), %other ]
+
+ %retval = alloca i32, align 4 ; [#uses=1 type=i32*]
+ store i32 0, i32* %retval
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32]
+ br label %other
+
+other:
+ br i1 0, label %zero, label %last
+
+last:
+ ret i32 1
+}
+
+declare i32 @printf(i8*, ...)
+
diff --git a/tests/cubegeom.c b/tests/cubegeom.c
index fac0da2b..96d56339 100644
--- a/tests/cubegeom.c
+++ b/tests/cubegeom.c
@@ -194,8 +194,14 @@ int main(int argc, char *argv[])
// sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B
glVertexPointer(3, GL_FLOAT, 32, (void*)0); // all these apply to the ARRAY_BUFFER that is bound
glTexCoordPointer(2, GL_FLOAT, 32, (void*)16);
+
glClientActiveTexture(GL_TEXTURE1); // XXX seems to be ignored in native build
glTexCoordPointer(2, GL_SHORT, 32, (void*)24);
+ glGetIntegerv(GL_TEXTURE_COORD_ARRAY_SIZE, &tempInt); assert(tempInt == 2);
+ glGetIntegerv(GL_TEXTURE_COORD_ARRAY_TYPE, &tempInt); assert(tempInt == GL_SHORT);
+ glGetIntegerv(GL_TEXTURE_COORD_ARRAY_STRIDE, &tempInt); assert(tempInt == 32);
+ glGetPointerv(GL_TEXTURE_COORD_ARRAY_POINTER, &tempPtr); assert(tempPtr == (void *)24);
+
glClientActiveTexture(GL_TEXTURE0); // likely not needed, it is a cleanup
glNormalPointer(GL_BYTE, 32, (void*)12);
glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)28);
diff --git a/tests/mmap_file.c b/tests/mmap_file.c
new file mode 100644
index 00000000..6eed95e0
--- /dev/null
+++ b/tests/mmap_file.c
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <sys/mman.h>
+#include <emscripten.h>
+#include <string.h>
+#include <assert.h>
+
+int main() {
+ printf("*\n");
+ FILE *f = fopen("data.dat", "r");
+ char *m;
+ m = (char*)mmap(NULL, 9000, PROT_READ, MAP_PRIVATE, fileno(f), 0);
+ for (int i = 0; i < 20; i++) putchar(m[i]);
+ assert(!strncmp(m, "data from the file .", 20));
+ munmap(m, 9000);
+ printf("\n");
+ m = (char*)mmap(NULL, 9000, PROT_READ, MAP_PRIVATE, fileno(f), 5);
+ for (int i = 0; i < 20; i++) putchar(m[i]);
+ assert(!strncmp(m, "from the file ......", 20));
+ munmap(m, 9000);
+ printf("\n*\n");
+
+#ifdef REPORT_RESULT
+ int result = 1;
+ REPORT_RESULT();
+#endif
+ return 0;
+}
diff --git a/tests/test_browser.py b/tests/test_browser.py
index 2ff9106b..d52f109f 100644
--- a/tests/test_browser.py
+++ b/tests/test_browser.py
@@ -338,7 +338,7 @@ If manually bisecting:
("somefile.txt@/directory/file.txt", "/directory/file.txt"),
("somefile.txt@/directory/file.txt", "directory/file.txt"),
(absolute_src_path + "@/directory/file.txt", "directory/file.txt")]
-
+
for test in test_cases:
(srcpath, dstpath) = test
print 'Testing', srcpath, dstpath
@@ -346,6 +346,11 @@ If manually bisecting:
Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', srcpath, '-o', 'page.html']).communicate()
self.run_browser('page.html', 'You should see |load me right before|.', '/report_result?1')
+ # Test that '--no-heap-copy' works.
+ make_main('somefile.txt')
+ Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', 'somefile.txt', '--no-heap-copy', '-o', 'page.html']).communicate()
+ self.run_browser('page.html', 'You should see |load me right before|.', '/report_result?1')
+
# By absolute path
make_main('somefile.txt') # absolute becomes relative
@@ -1566,3 +1571,7 @@ keydown(100);keyup(100); // trigger the end
Popen([PYTHON, EMCC, path_from_root('tests', 'browser_module.cpp'), '-o', 'module.js', '-O2', '-s', 'SIDE_MODULE=1', '-s', 'DLOPEN_SUPPORT=1', '-s', 'EXPORTED_FUNCTIONS=["_one", "_two"]']).communicate()
self.btest('browser_main.cpp', args=['-O2', '-s', 'MAIN_MODULE=1', '-s', 'DLOPEN_SUPPORT=1'], expected='8')
+ def test_mmap_file(self):
+ open(self.in_dir('data.dat'), 'w').write('data from the file ' + ('.' * 9000))
+ for extra_args in [[], ['--no-heap-copy']]:
+ self.btest(path_from_root('tests', 'mmap_file.c'), expected='1', args=['--preload-file', 'data.dat'] + extra_args)
diff --git a/tests/test_core.py b/tests/test_core.py
index 189da2bc..b2147d49 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -3814,7 +3814,6 @@ def process(filename):
self.do_run(open(path_from_root('tests', 'emscripten_get_now.cpp')).read(), 'Timer resolution is good.')
def test_inlinejs(self):
- if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code
if not self.is_le32(): return self.skip('le32 needed for inline js')
src = r'''
#include <stdio.h>
@@ -3842,7 +3841,6 @@ def process(filename):
self.do_run(src, 'Inline JS is very cool\n3.64\n') # TODO 1\n2\n3\n1\n2\n3\n')
def test_inlinejs2(self):
- if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code
if not self.is_le32(): return self.skip('le32 needed for inline js')
src = r'''
#include <stdio.h>
@@ -8594,30 +8592,13 @@ void*:16
def test_mmap_file(self):
if self.emcc_args is None: return self.skip('requires emcc')
- self.emcc_args += ['--embed-file', 'data.dat']
+ for extra_args in [[], ['--no-heap-copy']]:
+ self.emcc_args += ['--embed-file', 'data.dat'] + extra_args
- open(self.in_dir('data.dat'), 'w').write('data from the file ' + ('.' * 9000))
+ open(self.in_dir('data.dat'), 'w').write('data from the file ' + ('.' * 9000))
- src = r'''
- #include <stdio.h>
- #include <sys/mman.h>
-
- int main() {
- printf("*\n");
- FILE *f = fopen("data.dat", "r");
- char *m;
- m = (char*)mmap(NULL, 9000, PROT_READ, MAP_PRIVATE, fileno(f), 0);
- for (int i = 0; i < 20; i++) putchar(m[i]);
- munmap(m, 9000);
- printf("\n");
- m = (char*)mmap(NULL, 9000, PROT_READ, MAP_PRIVATE, fileno(f), 5);
- for (int i = 0; i < 20; i++) putchar(m[i]);
- munmap(m, 9000);
- printf("\n*\n");
- return 0;
- }
- '''
- self.do_run(src, '*\ndata from the file .\nfrom the file ......\n*\n')
+ src = open(path_from_root('tests', 'mmap_file.c')).read()
+ self.do_run(src, '*\ndata from the file .\nfrom the file ......\n*\n')
def test_cubescript(self):
if self.emcc_args is None: return self.skip('requires emcc')
@@ -8660,6 +8641,128 @@ void*:16
main = main[:main.find('\n}')]
assert main.count('\n') == 7, 'must not emit too many postSets: %d' % main.count('\n')
+ def test_simd(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('needs ta2')
+ if Settings.ASM_JS: Settings.ASM_JS = 2 # does not validate
+ src = r'''
+#include <stdio.h>
+
+#include <emscripten/vector.h>
+
+static inline float32x4 __attribute__((always_inline))
+_mm_set_ps(const float __Z, const float __Y, const float __X, const float __W)
+{
+ return (float32x4){ __W, __X, __Y, __Z };
+}
+
+static __inline__ float32x4 __attribute__((__always_inline__))
+_mm_setzero_ps(void)
+{
+ return (float32x4){ 0.0, 0.0, 0.0, 0.0 };
+}
+
+int main(int argc, char **argv) {
+ float data[8];
+ for (int i = 0; i < 32; i++) data[i] = (1+i+argc)*(2+i+argc*argc); // confuse optimizer
+ {
+ float32x4 *a = (float32x4*)&data[0];
+ float32x4 *b = (float32x4*)&data[4];
+ float32x4 c, d;
+ c = *a;
+ d = *b;
+ printf("1floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]);
+ c = c+d;
+ printf("2floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]);
+ d = c*d;
+ printf("3floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]);
+ c = _mm_setzero_ps();
+ printf("zeros %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3]);
+ }
+ {
+ uint32x4 *a = (uint32x4*)&data[0];
+ uint32x4 *b = (uint32x4*)&data[4];
+ uint32x4 c, d, e, f;
+ c = *a;
+ d = *b;
+ printf("4uints! %d, %d, %d, %d %d, %d, %d, %d\n", c[0], c[1], c[2], c[3], d[0], d[1], d[2], d[3]);
+ e = c+d;
+ f = c-d;
+ printf("5uints! %d, %d, %d, %d %d, %d, %d, %d\n", e[0], e[1], e[2], e[3], f[0], f[1], f[2], f[3]);
+ e = c&d;
+ f = c|d;
+ e = ~c&d;
+ f = c^d;
+ printf("5uintops! %d, %d, %d, %d %d, %d, %d, %d\n", e[0], e[1], e[2], e[3], f[0], f[1], f[2], f[3]);
+ }
+ {
+ float32x4 c, d, e, f;
+ c = _mm_set_ps(9.0, 4.0, 0, -9.0);
+ d = _mm_set_ps(10.0, 14.0, -12, -2.0);
+ printf("6floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]);
+ printf("7calcs: %d\n", emscripten_float32x4_signmask(c)); // TODO: just not just compilation but output as well
+ }
+
+ return 0;
+}
+ '''
+
+ self.do_run(src, '''1floats! 6, 12, 20, 30 42, 56, 72, 90
+2floats! 48, 68, 92, 120 42, 56, 72, 90
+3floats! 48, 68, 92, 120 2016, 3808, 6624, 10800
+zeros 0, 0, 0, 0
+4uints! 1086324736, 1094713344, 1101004800, 1106247680 1109917696, 1113587712, 1116733440, 1119092736
+5uints! -2098724864, -2086666240, -2077229056, -2069626880 -23592960, -18874368, -15728640, -12845056
+5uintops! 36175872, 35651584, 34603008, 33816576 48758784, 52428800, 53477376, 54788096
+6floats! -9, 0, 4, 9 -2, -12, 14, 10
+''')
+
+ def test_simd2(self):
+ if Settings.ASM_JS: Settings.ASM_JS = 2 # does not validate
+
+ self.do_run(r'''
+ #include <stdio.h>
+
+ typedef float __m128 __attribute__ ((__vector_size__ (16)));
+
+ static inline __m128 __attribute__((always_inline))
+ _mm_set_ps(const float __Z, const float __Y, const float __X, const float __W)
+ {
+ return (__m128){ __W, __X, __Y, __Z };
+ }
+
+ static inline void __attribute__((always_inline))
+ _mm_store_ps(float *__P, __m128 __A)
+ {
+ *(__m128 *)__P = __A;
+ }
+
+ static inline __m128 __attribute__((always_inline))
+ _mm_add_ps(__m128 __A, __m128 __B)
+ {
+ return __A + __B;
+ }
+
+ using namespace std;
+
+ int main(int argc, char ** argv) {
+ float __attribute__((__aligned__(16))) ar[4];
+ __m128 v1 = _mm_set_ps(9.0, 4.0, 0, -9.0);
+ __m128 v2 = _mm_set_ps(7.0, 3.0, 2.5, 1.0);
+ __m128 v3 = _mm_add_ps(v1, v2);
+ _mm_store_ps(ar, v3);
+
+ for (int i = 0; i < 4; i++) {
+ printf("%f\n", ar[i]);
+ }
+
+ return 0;
+ }
+ ''', '''-8.000000
+2.500000
+7.000000
+16.000000
+''')
+
def test_gcc_unmangler(self):
Settings.NAMED_GLOBALS = 1 # test coverage for this
diff --git a/tests/test_other.py b/tests/test_other.py
index 185e83d1..584f6714 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -2010,69 +2010,51 @@ a(int [32], char [5]*)
try_delete(path_from_root('tests', 'Module-exports', 'test.js'))
try_delete(path_from_root('tests', 'Module-exports', 'test.js.map'))
- def test_simd(self):
- self.clear()
- Popen([PYTHON, EMCC, path_from_root('tests', 'linpack.c'), '-O2', '-DSP', '--llvm-opts', '''['-O3', '-vectorize', '-vectorize-loops', '-bb-vectorize-vector-bits=128', '-force-vector-width=4']''']).communicate()
- self.assertContained('Unrolled Single Precision', run_js('a.out.js'))
-
- def test_simd2(self):
- self.clear()
+ def test_fs_stream_proto(self):
open('src.cpp', 'w').write(r'''
#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
-#include <emscripten/vector.h>
-
-static inline float32x4 __attribute__((always_inline))
-_mm_set_ps(const float __Z, const float __Y, const float __X, const float __W)
+int main()
{
- return (float32x4){ __W, __X, __Y, __Z };
-}
-
-int main(int argc, char **argv) {
- float data[8];
- for (int i = 0; i < 32; i++) data[i] = (1+i+argc)*(2+i+argc*argc);
- {
- float32x4 *a = (float32x4*)&data[0];
- float32x4 *b = (float32x4*)&data[4];
- float32x4 c, d;
- c = *a;
- d = *b;
- printf("1floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]);
- c = c+d;
- printf("2floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]);
- d = c*d;
- printf("3floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]);
- }
- {
- uint32x4 *a = (uint32x4*)&data[0];
- uint32x4 *b = (uint32x4*)&data[4];
- uint32x4 c, d, e, f;
- c = *a;
- d = *b;
- printf("4uints! %d, %d, %d, %d %d, %d, %d, %d\n", c[0], c[1], c[2], c[3], d[0], d[1], d[2], d[3]);
- e = c+d;
- f = c-d;
- printf("5uints! %d, %d, %d, %d %d, %d, %d, %d\n", e[0], e[1], e[2], e[3], f[0], f[1], f[2], f[3]);
- }
- {
- float32x4 c, d, e, f;
- c = _mm_set_ps(9.0, 4.0, 0, -9.0);
- d = _mm_set_ps(10.0, 14.0, -12, -2.0);
- printf("6floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]);
- }
-
- return 0;
+ int file_size = 0;
+ int h = open("src.cpp", O_RDONLY, 0666);
+ if (0 != h)
+ {
+ FILE* file = fdopen(h, "rb");
+ if (0 != file)
+ {
+ fseek(file, 0, SEEK_END);
+ file_size = ftell(file);
+ fseek(file, 0, SEEK_SET);
+ }
+ else
+ {
+ printf("fdopen() failed: %s\n", strerror(errno));
+ return 10;
+ }
+ close(h);
+ printf("File size: %d\n", file_size);
+ }
+ else
+ {
+ printf("open() failed: %s\n", strerror(errno));
+ return 10;
+ }
+ return 0;
}
''')
+ Popen([PYTHON, EMCC, 'src.cpp', '--embed-file', 'src.cpp']).communicate()
+ for engine in JS_ENGINES:
+ out = run_js('a.out.js', engine=engine, stderr=PIPE, full_output=True)
+ self.assertContained('File size: 722', out)
- for opts in [[], ['-O1'], ['-O2']]:
- print opts
- Popen([PYTHON, EMCC, 'src.cpp'] + opts).communicate()
- self.assertContained('''1floats! 6, 12, 20, 30 42, 56, 72, 90
-2floats! 48, 68, 92, 120 42, 56, 72, 90
-3floats! 48, 68, 92, 120 2016, 3808, 6624, 10800
-4uints! 1086324736, 1094713344, 1101004800, 1106247680 1109917696, 1113587712, 1116733440, 1119092736
-5uints! -2098724864, -2086666240, -2077229056, -2069626880 -23592960, -18874368, -15728640, -12845056
-6floats! -9, 0, 4, 9 -2, -12, 14, 10
-''', run_js('a.out.js'))
+ def test_simd(self):
+ self.clear()
+ Popen([PYTHON, EMCC, path_from_root('tests', 'linpack.c'), '-O2', '-DSP', '--llvm-opts', '''['-O3', '-vectorize', '-vectorize-loops', '-bb-vectorize-vector-bits=128', '-force-vector-width=4']''']).communicate()
+ self.assertContained('Unrolled Single Precision', run_js('a.out.js'))
diff --git a/tests/test_sanity.py b/tests/test_sanity.py
index a0fff252..a405c3a3 100644
--- a/tests/test_sanity.py
+++ b/tests/test_sanity.py
@@ -217,7 +217,11 @@ class sanity(RunnerCore):
try:
os.environ['EM_IGNORE_SANITY'] = '1'
- for version, succeed in [('v0.7.9', False), ('v0.8.0', True), ('v0.8.1', True), ('cheez', False)]:
+ for version, succeed in [('v0.7.9', False),
+ ('v0.8.0', True),
+ ('v0.8.1', True),
+ ('v0.10.21-pre', True),
+ ('cheez', False)]:
f = open(path_from_root('tests', 'fake', 'nodejs'), 'w')
f.write('#!/bin/sh\n')
f.write('''if [ $1 = "--version" ]; then
diff --git a/tests/test_sockets.py b/tests/test_sockets.py
index d2bc46a2..e1caa150 100644
--- a/tests/test_sockets.py
+++ b/tests/test_sockets.py
@@ -400,3 +400,29 @@ class sockets(BrowserCore):
expected = '1'
self.run_browser(host_outfile, '.', ['/report_result?' + e for e in expected])
+ def test_nodejs_sockets_echo(self):
+ # This test checks that sockets work when the client code is run in Node.js
+ # Run with ./runner.py sockets.test_nodejs_sockets_echo
+ if not NODE_JS in JS_ENGINES:
+ return self.skip('node is not present')
+
+ sockets_include = '-I'+path_from_root('tests', 'sockets')
+
+ # Websockify-proxied servers can't run dgram tests
+ harnesses = [
+ # Websockify doesn't seem to like ws.WebSocket clients TODO check if this is a ws issue or Websockify issue
+ #(WebsockifyServerHarness(os.path.join('sockets', 'test_sockets_echo_server.c'), [sockets_include], 49160), 0),
+ (CompiledServerHarness(os.path.join('sockets', 'test_sockets_echo_server.c'), [sockets_include, '-DTEST_DGRAM=0'], 49161), 0),
+ (CompiledServerHarness(os.path.join('sockets', 'test_sockets_echo_server.c'), [sockets_include, '-DTEST_DGRAM=1'], 49162), 1)
+ ]
+
+ for harness, datagram in harnesses:
+ with harness:
+ Popen([PYTHON, EMCC, path_from_root('tests', 'sockets', 'test_sockets_echo_client.c'), '-o', path_from_root('tests', 'sockets', 'client.js'), '-DSOCKK=%d' % harness.listen_port, '-DREPORT_RESULT=int dummy'], stdout=PIPE, stderr=PIPE).communicate()
+
+ self.assertContained('do_msg_read: read 14 bytes', run_js(path_from_root('tests', 'sockets', 'client.js'), engine=NODE_JS))
+
+ # Tidy up files that might have been created by this test.
+ try_delete(path_from_root('tests', 'sockets', 'client.js'))
+ try_delete(path_from_root('tests', 'sockets', 'client.js.map'))
+
diff --git a/tools/file_packager.py b/tools/file_packager.py
index 1d0ec447..3ba5b23f 100644
--- a/tools/file_packager.py
+++ b/tools/file_packager.py
@@ -11,7 +11,7 @@ data downloads.
Usage:
- file_packager.py TARGET [--preload A [B..]] [--embed C [D..]] [--compress COMPRESSION_DATA] [--crunch[=X]] [--js-output=OUTPUT.js] [--no-force]
+ file_packager.py TARGET [--preload A [B..]] [--embed C [D..]] [--compress COMPRESSION_DATA] [--crunch[=X]] [--js-output=OUTPUT.js] [--no-force] [--use-preload-cache] [--no-heap-copy]
--crunch=X Will compress dxt files to crn with quality level X. The crunch commandline tool must be present
and CRUNCH should be defined in ~/.emscripten that points to it. JS crunch decompressing code will
@@ -27,6 +27,10 @@ Usage:
--use-preload-cache Stores package in IndexedDB so that subsequent loads don't need to do XHR. Checks package version.
+ --no-heap-copy If specified, the preloaded filesystem is not copied inside the Emscripten HEAP, but kept in a separate typed array outside it.
+ The default, if this is not specified, is to embed the VFS inside the HEAP, so that mmap()ing files in it is a no-op.
+ Passing this flag optimizes for fread() usage, omitting it optimizes for mmap() usage.
+
Notes:
* The file packager generates unix-style file paths. So if you are on windows and a file is accessed at
@@ -43,7 +47,7 @@ from shared import Compression, execute, suffix, unsuffixed
from subprocess import Popen, PIPE, STDOUT
if len(sys.argv) == 1:
- print '''Usage: file_packager.py TARGET [--preload A...] [--embed B...] [--compress COMPRESSION_DATA] [--crunch[=X]] [--js-output=OUTPUT.js] [--no-force] [--use-preload-cache]
+ print '''Usage: file_packager.py TARGET [--preload A...] [--embed B...] [--compress COMPRESSION_DATA] [--crunch[=X]] [--js-output=OUTPUT.js] [--no-force] [--use-preload-cache] [--no-heap-copy]
See the source for more details.'''
sys.exit(0)
@@ -70,7 +74,12 @@ crunch = 0
plugins = []
jsoutput = None
force = True
+# If set to True, IndexedDB (IDBFS in library_idbfs.js) is used to locally cache VFS XHR so that subsequent
+# page loads can read the data from the offline cache instead.
use_preload_cache = False
+# If set to True, the blob received from XHR is moved to the Emscripten HEAP, optimizing for mmap() performance.
+# If set to False, the XHR blob is kept intact, and fread()s etc. are performed directly to that data. This optimizes for minimal memory usage and fread() performance.
+no_heap_copy = True
for arg in sys.argv[1:]:
if arg == '--preload':
@@ -91,6 +100,8 @@ for arg in sys.argv[1:]:
force = False
elif arg == '--use-preload-cache':
use_preload_cache = True
+ elif arg == '--no-heap-copy':
+ no_heap_copy = False
elif arg.startswith('--js-output'):
jsoutput = arg.split('=')[1] if '=' in arg else None
elif arg.startswith('--crunch'):
@@ -414,12 +425,18 @@ for file_ in data_files:
if has_preloaded:
# Get the big archive and split it up
- use_data = '''
+ if no_heap_copy:
+ use_data = '''
// copy the entire loaded file into a spot in the heap. Files will refer to slices in that. They cannot be freed though.
var ptr = Module['_malloc'](byteArray.length);
Module['HEAPU8'].set(byteArray, ptr);
DataRequest.prototype.byteArray = Module['HEAPU8'].subarray(ptr, ptr+byteArray.length);
'''
+ else:
+ use_data = '''
+ // Reuse the bytearray from the XHR as the source for file reads.
+ DataRequest.prototype.byteArray = byteArray;
+'''
for file_ in data_files:
if file_['mode'] == 'preload':
use_data += ' DataRequest.prototype.requests["%s"].onload();\n' % (file_['dstpath'])
diff --git a/tools/shared.py b/tools/shared.py
index 108a48a4..f6c0cc95 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -284,7 +284,7 @@ def check_node_version():
try:
node = listify(NODE_JS)
actual = Popen(node + ['--version'], stdout=PIPE).communicate()[0].strip()
- version = tuple(map(int, actual.replace('v', '').split('.')))
+ version = tuple(map(int, actual.replace('v', '').replace('-pre', '').split('.')))
if version >= EXPECTED_NODE_VERSION:
return True
logging.warning('node version appears too old (seeing "%s", expected "%s")' % (actual, 'v' + ('.'.join(map(str, EXPECTED_NODE_VERSION)))))