summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-08-30 11:21:48 -0700
committerAlon Zakai <alonzakai@gmail.com>2013-08-30 11:21:48 -0700
commitb5b49215d4a40566380a769f47a9c1cce74a28b0 (patch)
tree68308b6059798a81f24f6a8a1ac28a0091c5d066
parent1cc28b8e9e94267041bc71afebfbbe3059db4a3f (diff)
parentb895cdc7df2085d324003c9df582a3dcc1927697 (diff)
Merge branch 'incoming'
-rw-r--r--AUTHORS1
-rw-r--r--src/analyzer.js8
-rw-r--r--src/jsifier.js18
-rw-r--r--src/library.js38
-rw-r--r--src/library_browser.js22
-rw-r--r--src/library_fs.js90
-rw-r--r--src/library_memfs.js6
-rw-r--r--src/library_path.js3
-rw-r--r--src/library_sdl.js26
-rw-r--r--src/library_tty.js41
-rw-r--r--src/parseTools.js2
-rw-r--r--src/settings.js6
-rw-r--r--tests/cases/callwithstructural64_ta2.ll29
-rw-r--r--tests/cases/callwithstructural64_ta2.txt1
-rw-r--r--tests/cases/callwithstructural_ta2.ll29
-rw-r--r--tests/cases/callwithstructural_ta2.txt1
-rw-r--r--tests/cases/structinparam.ll36
-rw-r--r--tests/cases/structinparam.txt2
-rw-r--r--tests/emscripten_get_now.cpp46
-rw-r--r--tests/file_db.cpp47
-rw-r--r--tests/filesystem/src.js7
-rw-r--r--tests/module/test_stdin.c57
-rw-r--r--tests/msvc10/glbook_10_MultiTexture.vcxproj4
-rw-r--r--tests/msvc10/glbook_11_Multisample.vcxproj4
-rw-r--r--tests/msvc10/glbook_11_Stencil_Test.vcxproj4
-rw-r--r--tests/msvc10/glbook_13_ParticleSystem.vcxproj4
-rw-r--r--tests/msvc10/glbook_15_Hello_Triangle_KD.vcxproj4
-rw-r--r--tests/msvc10/glbook_2_Hello_Triangle.vcxproj4
-rw-r--r--tests/msvc10/glbook_8_Simple_VertexShader.vcxproj4
-rw-r--r--tests/msvc10/glbook_9_MipMap2D.vcxproj4
-rw-r--r--tests/msvc10/glbook_9_Simple_Texture2D.vcxproj4
-rw-r--r--tests/msvc10/glbook_9_Simple_TextureCubemap.vcxproj4
-rw-r--r--tests/msvc10/glbook_9_TextureWrap.vcxproj4
-rw-r--r--tests/termios/test_tcgetattr.c61
-rw-r--r--tests/test_browser.py14
-rw-r--r--tests/test_core.py24
-rw-r--r--tests/test_other.py22
-rw-r--r--tests/unistd/curdir.js5
-rw-r--r--tests/unistd/io.c13
-rw-r--r--tests/unistd/io.js61
-rw-r--r--tests/unistd/io.out5
-rw-r--r--tools/file_packager.py20
-rw-r--r--tools/find_bigfuncs.py2
-rw-r--r--tools/js-optimizer.js12
-rw-r--r--tools/js_optimizer.py56
-rw-r--r--tools/jsrun.py3
-rw-r--r--tools/test-js-optimizer-asm-outline1-output.js64
-rw-r--r--tools/test-js-optimizer-asm-outline1.js2
48 files changed, 769 insertions, 155 deletions
diff --git a/AUTHORS b/AUTHORS
index 59eb27d3..a0475661 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -95,4 +95,5 @@ a license to everyone to use it as detailed in LICENSE.)
* Nick Bray <ncbray@chromium.org> (copyright owned by Google, Inc.)
* Aidan Hobson Sayers <aidanhs@cantab.net>
* Charlie Birks <admin@daftgames.net>
+* Ranger Harke <ranger.harke@autodesk.com> (copyright owned by Autodesk, Inc.)
diff --git a/src/analyzer.js b/src/analyzer.js
index 2a7d64f5..b20dedff 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -281,6 +281,14 @@ function analyzer(data, sidePass) {
Array.prototype.splice.apply(params, [i, 1].concat(toAdd));
i += toAdd.length;
continue;
+ } else if (param.intertype == 'structvalue') {
+ // 'flatten' out the struct into scalars
+ var toAdd = param.params;
+ toAdd.forEach(function(param) {
+ param.byval = 0;
+ });
+ Array.prototype.splice.apply(params, [i, 1].concat(toAdd));
+ continue; // do not increment i; proceed to process the new params
}
i++;
}
diff --git a/src/jsifier.js b/src/jsifier.js
index 179a910a..7273f54c 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -23,7 +23,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var mainPass = !functionsOnly;
if (mainPass) {
- var shellFile = SHELL_FILE ? SHELL_FILE : (BUILD_AS_SHARED_LIB ? 'shell_sharedlib.js' : 'shell.js');
+ var shellFile = SHELL_FILE ? SHELL_FILE : (BUILD_AS_SHARED_LIB || SIDE_MODULE ? 'shell_sharedlib.js' : 'shell.js');
if (phase == 'pre') {
// We will start to print out the data, but must do so carefully - we are
@@ -47,10 +47,11 @@ function JSify(data, functionsOnly, givenFunctions) {
var shellParts = read(shellFile).split('{{BODY}}');
print(processMacros(preprocess(shellParts[0])));
- var preFile = BUILD_AS_SHARED_LIB ? 'preamble_sharedlib.js' : 'preamble.js';
+ var preFile = BUILD_AS_SHARED_LIB || SIDE_MODULE ? 'preamble_sharedlib.js' : 'preamble.js';
var pre = processMacros(preprocess(read(preFile).replace('{{RUNTIME}}', getRuntime())));
print(pre);
+ // Populate implementedFunctions. Note that this is before types, and will be updated later.
data.unparsedFunctions.forEach(function(func) {
Functions.implementedFunctions[func.ident] = Functions.getSignature(func.returnType, func.params.map(function(param) { return param.type }));
});
@@ -80,7 +81,7 @@ function JSify(data, functionsOnly, givenFunctions) {
if (phase == 'pre') {
var libFuncsToInclude;
if (INCLUDE_FULL_LIBRARY) {
- assert(!BUILD_AS_SHARED_LIB, 'Cannot have both INCLUDE_FULL_LIBRARY and BUILD_AS_SHARED_LIB set.')
+ assert(!(BUILD_AS_SHARED_LIB || SIDE_MODULE), 'Cannot have both INCLUDE_FULL_LIBRARY and BUILD_AS_SHARED_LIB/SIDE_MODULE set.')
libFuncsToInclude = [];
for (var key in LibraryManager.library) {
if (!key.match(/__(deps|postset|inline|asm|sig)$/)) {
@@ -454,7 +455,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var postsetId = ident + '__postset';
var postset = LibraryManager.library[postsetId];
- if (postset && !addedLibraryItems[postsetId]) {
+ if (postset && !addedLibraryItems[postsetId] && !SIDE_MODULE) {
addedLibraryItems[postsetId] = true;
ret.push({
intertype: 'GlobalVariablePostSet',
@@ -497,6 +498,7 @@ function JSify(data, functionsOnly, givenFunctions) {
Functions.libraryFunctions[ident.substr(1)] = 2;
}
}
+ if (SIDE_MODULE) return ';'; // we import into the side module js library stuff from the outside parent
if ((!ASM_JS || phase == 'pre') &&
(EXPORT_ALL || (ident in EXPORTED_FUNCTIONS))) {
contentText += '\nModule["' + ident + '"] = ' + ident + ';';
@@ -1835,7 +1837,7 @@ function JSify(data, functionsOnly, givenFunctions) {
print('Runtime.typeInfo = ' + JSON.stringify(Types.types));
print('Runtime.structMetadata = ' + JSON.stringify(Types.structMetadata));
}
- var postFile = BUILD_AS_SHARED_LIB ? 'postamble_sharedlib.js' : 'postamble.js';
+ var postFile = BUILD_AS_SHARED_LIB || SIDE_MODULE ? 'postamble_sharedlib.js' : 'postamble.js';
var postParts = processMacros(preprocess(read(postFile))).split('{{GLOBAL_VARS}}');
print(postParts[0]);
@@ -1871,6 +1873,12 @@ function JSify(data, functionsOnly, givenFunctions) {
// Data
if (mainPass) {
+ if (phase == 'pre') {
+ // types have been parsed, so we can figure out function signatures (which can use types)
+ data.unparsedFunctions.forEach(function(func) {
+ Functions.implementedFunctions[func.ident] = Functions.getSignature(func.returnType, func.params.map(function(param) { return param.type }));
+ });
+ }
substrate.addItems(data.functionStubs, 'FunctionStub');
assert(data.functions.length == 0);
} else {
diff --git a/src/library.js b/src/library.js
index 3ba2f56b..f6b3d5ef 100644
--- a/src/library.js
+++ b/src/library.js
@@ -2261,7 +2261,11 @@ LibraryManager.library = {
// void clearerr(FILE *stream);
// http://pubs.opengroup.org/onlinepubs/000095399/functions/clearerr.html
stream = FS.getStream(stream);
- if (stream) stream.error = false;
+ if (!stream) {
+ return;
+ }
+ stream.eof = false;
+ stream.error = false;
},
fclose__deps: ['close', 'fsync'],
fclose: function(stream) {
@@ -2322,7 +2326,6 @@ LibraryManager.library = {
if (streamObj.eof || streamObj.error) return -1;
var ret = _fread(_fgetc.ret, 1, 1, stream);
if (ret == 0) {
- streamObj.eof = true;
return -1;
} else if (ret == -1) {
streamObj.error = true;
@@ -5154,6 +5157,37 @@ LibraryManager.library = {
},
// ==========================================================================
+ // termios.h
+ // ==========================================================================
+ tcgetattr: function(fildes, termios_p) {
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/tcgetattr.html
+ var stream = FS.getStream(fildes);
+ if (!stream) {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
+ }
+ if (!stream.tty) {
+ ___setErrNo(ERRNO_CODES.ENOTTY);
+ return -1;
+ }
+ return 0;
+ },
+
+ tcsetattr: function(fildes, optional_actions, termios_p) {
+ // http://pubs.opengroup.org/onlinepubs/7908799/xsh/tcsetattr.html
+ var stream = FS.getStream(fildes);
+ if (!stream) {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
+ }
+ if (!stream.tty) {
+ ___setErrNo(ERRNO_CODES.ENOTTY);
+ return -1;
+ }
+ return 0;
+ },
+
+ // ==========================================================================
// time.h
// ==========================================================================
diff --git a/src/library_browser.js b/src/library_browser.js
index 591a3c11..235ccc78 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -830,15 +830,21 @@ mergeInto(LibraryManager.library, {
},
emscripten_get_now: function() {
- if (ENVIRONMENT_IS_NODE) {
- var t = process['hrtime']();
- return t[0] * 1e3 + t[1] / 1e6;
- }
- else if (ENVIRONMENT_IS_WEB && window['performance'] && window['performance']['now']) {
- return window['performance']['now']();
- } else {
- return Date.now();
+ if (!_emscripten_get_now.actual) {
+ if (ENVIRONMENT_IS_NODE) {
+ _emscripten_get_now.actual = function() {
+ 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'](); };
+ } else {
+ _emscripten_get_now.actual = Date.now;
+ }
}
+ return _emscripten_get_now.actual();
},
emscripten_create_worker: function(url) {
diff --git a/src/library_fs.js b/src/library_fs.js
index e1397356..1d9748d3 100644
--- a/src/library_fs.js
+++ b/src/library_fs.js
@@ -510,7 +510,7 @@ mergeInto(LibraryManager.library, {
return FS.create(path, mode);
},
createDataFile: function(parent, name, data, canRead, canWrite, canOwn) {
- var path = PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name);
+ var path = name ? PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name) : parent;
var mode = FS.getMode(canRead, canWrite);
var node = FS.create(path, mode);
if (data) {
@@ -530,7 +530,7 @@ mergeInto(LibraryManager.library, {
},
createDevice: function(parent, name, input, output) {
var path = PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name);
- var mode = input && output ? 0777 : (input ? 0333 : 0555);
+ var mode = FS.getMode(!!input, !!output);
if (!FS.createDevice.major) FS.createDevice.major = 64;
var dev = FS.makedev(FS.createDevice.major++, 0);
// Create a fake device that a set of stream ops to emulate
@@ -770,7 +770,7 @@ mergeInto(LibraryManager.library, {
Browser.init();
// TODO we should allow people to just pass in a complete filename instead
// of parent and name being that we just join them anyways
- var fullname = PATH.resolve(PATH.join(parent, name));
+ var fullname = name ? PATH.resolve(PATH.join(parent, name)) : parent;
function processData(byteArray) {
function finish(byteArray) {
if (!dontCreateFile) {
@@ -802,6 +802,90 @@ mergeInto(LibraryManager.library, {
}
},
+ indexedDB: function() {
+ return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
+ },
+
+ DB_NAME: function() {
+ return 'EM_FS_' + window.location.pathname;
+ },
+ DB_VERSION: 20,
+ DB_STORE_NAME: 'FILE_DATA',
+
+ // asynchronously saves a list of files to an IndexedDB. The DB will be created if not already existing.
+ saveFilesToDB: function(paths, onload, onerror) {
+ onload = onload || function(){};
+ onerror = onerror || function(){};
+ var indexedDB = FS.indexedDB();
+ try {
+ var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
+ } catch (e) {
+ return onerror(e);
+ }
+ openRequest.onupgradeneeded = function() {
+ console.log('creating db');
+ var db = openRequest.result;
+ db.createObjectStore(FS.DB_STORE_NAME);
+ };
+ openRequest.onsuccess = function() {
+ var db = openRequest.result;
+ var transaction = db.transaction([FS.DB_STORE_NAME], 'readwrite');
+ var files = transaction.objectStore(FS.DB_STORE_NAME);
+ var ok = 0, fail = 0, total = paths.length;
+ function finish() {
+ if (fail == 0) onload(); else onerror();
+ }
+ 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() };
+ });
+ transaction.onerror = onerror;
+ };
+ openRequest.onerror = onerror;
+ },
+
+ // asychronously loads a file from IndexedDB.
+ loadFilesFromDB: function(paths, onload, onerror) {
+ onload = onload || function(){};
+ onerror = onerror || function(){};
+ var indexedDB = FS.indexedDB();
+ try {
+ var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
+ } catch (e) {
+ return onerror(e);
+ }
+ openRequest.onupgradeneeded = onerror; // no database to load from
+ openRequest.onsuccess = function() {
+ var db = openRequest.result;
+ try {
+ var transaction = db.transaction([FS.DB_STORE_NAME], 'readonly');
+ } catch(e) {
+ onerror(e);
+ return;
+ }
+ var files = transaction.objectStore(FS.DB_STORE_NAME);
+ var ok = 0, fail = 0, total = paths.length;
+ function finish() {
+ if (fail == 0) onload(); else onerror();
+ }
+ paths.forEach(function(path) {
+ var getRequest = files.get(path);
+ getRequest.onsuccess = function() {
+ if (FS.analyzePath(path).exists) {
+ FS.unlink(path);
+ }
+ FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true);
+ ok++;
+ if (ok + fail == total) finish();
+ };
+ getRequest.onerror = function() { fail++; if (ok + fail == total) finish() };
+ });
+ transaction.onerror = onerror;
+ };
+ openRequest.onerror = onerror;
+ },
+
//
// general
//
diff --git a/src/library_memfs.js b/src/library_memfs.js
index 63326c42..354f5e95 100644
--- a/src/library_memfs.js
+++ b/src/library_memfs.js
@@ -2,17 +2,13 @@ mergeInto(LibraryManager.library, {
$MEMFS__deps: ['$FS'],
$MEMFS: {
// content modes
- CONTENT_OWNING: 1, // contains a subarray into the heap, and we own it - need to free() when no longer needed
+ CONTENT_OWNING: 1, // contains a subarray into the heap, and we own it, without copying (note: someone else needs to free() it, if that is necessary)
CONTENT_FLEXIBLE: 2, // has been modified or never set to anything, and is a flexible js array that can grow/shrink
CONTENT_FIXED: 3, // contains some fixed-size content written into it, in a typed array
ensureFlexible: function(node) {
if (node.contentMode !== MEMFS.CONTENT_FLEXIBLE) {
var contents = node.contents;
node.contents = Array.prototype.slice.call(contents);
- if (node.contentMode === MEMFS.CONTENT_OWNING) {
- assert(contents.byteOffset);
- Module['_free'](contents.byteOffset);
- }
node.contentMode = MEMFS.CONTENT_FLEXIBLE;
}
},
diff --git a/src/library_path.js b/src/library_path.js
index 2c2c016a..09808acd 100644
--- a/src/library_path.js
+++ b/src/library_path.js
@@ -68,6 +68,9 @@ mergeInto(LibraryManager.library, {
}
return f;
},
+ extname: function(path) {
+ return PATH.splitPath(path)[3];
+ },
join: function() {
var paths = Array.prototype.slice.call(arguments, 0);
return PATH.normalize(paths.filter(function(p, index) {
diff --git a/src/library_sdl.js b/src/library_sdl.js
index 1fb75724..d6cb6d18 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -46,6 +46,9 @@ var LibrarySDL = {
keyboardState: null,
keyboardMap: {},
+ canRequestFullscreen: false,
+ isRequestingFullscreen: false,
+
textInput: false,
startTime: null,
@@ -467,6 +470,23 @@ var LibrarySDL = {
SDL.DOMButtons[event.button] = 0;
}
+ // We can only request fullscreen as the result of user input.
+ // Due to this limitation, we toggle a boolean on keydown which
+ // SDL_WM_ToggleFullScreen will check and subsequently set another
+ // flag indicating for us to request fullscreen on the following
+ // keyup. This isn't perfect, but it enables SDL_WM_ToggleFullScreen
+ // to work as the result of a keypress (which is an extremely
+ // common use case).
+ if (event.type === 'keydown') {
+ SDL.canRequestFullscreen = true;
+ } else if (event.type === 'keyup') {
+ if (SDL.isRequestingFullscreen) {
+ Module['requestFullScreen'](true, true);
+ SDL.isRequestingFullscreen = false;
+ }
+ SDL.canRequestFullscreen = false;
+ }
+
// SDL expects a unicode character to be passed to its keydown events.
// Unfortunately, the browser APIs only provide a charCode property on
// keypress events, so we must backfill in keydown events with their
@@ -1282,7 +1302,11 @@ var LibrarySDL = {
Module['canvas'].cancelFullScreen();
return 1;
} else {
- return 0;
+ if (!SDL.canRequestFullscreen) {
+ return 0;
+ }
+ SDL.isRequestingFullscreen = true;
+ return 1;
}
},
diff --git a/src/library_tty.js b/src/library_tty.js
index 8f44cd07..53239989 100644
--- a/src/library_tty.js
+++ b/src/library_tty.js
@@ -1,17 +1,35 @@
mergeInto(LibraryManager.library, {
$TTY__deps: ['$FS'],
+ $TTY__postset: '__ATINIT__.unshift({ func: function() { TTY.init() } });' +
+ '__ATEXIT__.push({ func: function() { TTY.shutdown() } });' +
+ 'TTY.utf8 = new Runtime.UTF8Processor();',
$TTY: {
ttys: [],
+ init: function () {
+ if (ENVIRONMENT_IS_NODE) {
+ // currently, FS.init does not distinguish if process.stdin is a file or TTY
+ // device, it always assumes it's a TTY device. because of this, we're forcing
+ // process.stdin to UTF8 encoding to at least make stdin reading compatible
+ // with text files until FS.init can be refactored.
+ process['stdin']['setEncoding']('utf8');
+ }
+ },
+ shutdown: function() {
+ if (ENVIRONMENT_IS_NODE) {
+ // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)?
+ // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation
+ // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists?
+ // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle
+ // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call
+ process['stdin']['pause']();
+ }
+ },
register: function(dev, ops) {
TTY.ttys[dev] = { input: [], output: [], ops: ops };
FS.registerDevice(dev, TTY.stream_ops);
},
stream_ops: {
open: function(stream) {
- // this wouldn't be required if the library wasn't eval'd at first...
- if (!TTY.utf8) {
- TTY.utf8 = new Runtime.UTF8Processor();
- }
var tty = TTY.ttys[stream.node.rdev];
if (!tty) {
throw new FS.ErrnoError(ERRNO_CODES.ENODEV);
@@ -66,17 +84,22 @@ mergeInto(LibraryManager.library, {
return i;
}
},
- // NOTE: This is weird to support stdout and stderr
- // overrides in addition to print and printErr overrides.
default_tty_ops: {
+ // get_char has 3 particular return values:
+ // a.) the next character represented as an integer
+ // b.) undefined to signal that no data is currently available
+ // c.) null to signal an EOF
get_char: function(tty) {
if (!tty.input.length) {
var result = null;
if (ENVIRONMENT_IS_NODE) {
- if (process.stdin.destroyed) {
- return undefined;
+ result = process['stdin']['read']();
+ if (!result) {
+ if (process['stdin']['_readableState'] && process['stdin']['_readableState']['ended']) {
+ return null; // EOF
+ }
+ return undefined; // no data available
}
- result = process.stdin.read();
} else if (typeof window != 'undefined' &&
typeof window.prompt == 'function') {
// Browser.
diff --git a/src/parseTools.js b/src/parseTools.js
index 046dac1b..66354dca 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -430,6 +430,8 @@ function parseParamTokens(params) {
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);
diff --git a/src/settings.js b/src/settings.js
index 03b4ed64..02423ba5 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -874,9 +874,9 @@ var C_DEFINES = {
'SOCK_DGRAM': '2',
'SOCK_STREAM': '1',
'STDC_HEADERS': '1',
- 'STDERR_FILENO': '2',
- 'STDIN_FILENO': '0',
- 'STDOUT_FILENO': '1',
+ 'STDERR_FILENO': '3',
+ 'STDIN_FILENO': '1',
+ 'STDOUT_FILENO': '2',
'S_BLKSIZE': '1024',
'S_ENFMT': '0002000',
'S_IEXEC': '0000100',
diff --git a/tests/cases/callwithstructural64_ta2.ll b/tests/cases/callwithstructural64_ta2.ll
new file mode 100644
index 00000000..d16b0e87
--- /dev/null
+++ b/tests/cases/callwithstructural64_ta2.ll
@@ -0,0 +1,29 @@
+; ModuleID = 'foo.bc'
+target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32"
+target triple = "le32-unknown-nacl"
+
+%ac = type { i8*, i64 }
+
+@0 = constant [9 x i8] c"func %s\0A\00"
+@1 = constant [4 x i8] c"foo\00"
+
+declare void @llvm.trap() noreturn nounwind
+
+define void @direct(%ac) {
+entry:
+ %str = alloca %ac
+ store %ac %0, %ac* %str
+ %1 = getelementptr inbounds %ac* %str, i32 0, i32 0
+ %2 = load i8** %1
+ call void (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @0, i32 0, i32 0), i8* %2)
+ ret void
+}
+
+declare void @printf(i8*, ...)
+
+define i32 @main() {
+entry:
+ call void @direct(%ac { i8* getelementptr inbounds ([4 x i8]* @1, i32 0, i32 0), i64 3 })
+ ret i32 0
+}
+
diff --git a/tests/cases/callwithstructural64_ta2.txt b/tests/cases/callwithstructural64_ta2.txt
new file mode 100644
index 00000000..51a6ac7c
--- /dev/null
+++ b/tests/cases/callwithstructural64_ta2.txt
@@ -0,0 +1 @@
+func foo
diff --git a/tests/cases/callwithstructural_ta2.ll b/tests/cases/callwithstructural_ta2.ll
new file mode 100644
index 00000000..bc6f852a
--- /dev/null
+++ b/tests/cases/callwithstructural_ta2.ll
@@ -0,0 +1,29 @@
+; ModuleID = 'foo.bc'
+target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32"
+target triple = "le32-unknown-nacl"
+
+%ac = type { i8*, i32 }
+
+@0 = constant [9 x i8] c"func %s\0A\00"
+@1 = constant [4 x i8] c"foo\00"
+
+declare void @llvm.trap() noreturn nounwind
+
+define void @direct(%ac) {
+entry:
+ %str = alloca %ac
+ store %ac %0, %ac* %str
+ %1 = getelementptr inbounds %ac* %str, i32 0, i32 0
+ %2 = load i8** %1
+ call void (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @0, i32 0, i32 0), i8* %2)
+ ret void
+}
+
+declare void @printf(i8*, ...)
+
+define i32 @main() {
+entry:
+ call void @direct(%ac { i8* getelementptr inbounds ([4 x i8]* @1, i32 0, i32 0), i32 3 })
+ ret i32 0
+}
+
diff --git a/tests/cases/callwithstructural_ta2.txt b/tests/cases/callwithstructural_ta2.txt
new file mode 100644
index 00000000..51a6ac7c
--- /dev/null
+++ b/tests/cases/callwithstructural_ta2.txt
@@ -0,0 +1 @@
+func foo
diff --git a/tests/cases/structinparam.ll b/tests/cases/structinparam.ll
new file mode 100644
index 00000000..d81f5e67
--- /dev/null
+++ b/tests/cases/structinparam.ll
@@ -0,0 +1,36 @@
+; ModuleID = 'min.bc'
+target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32"
+target triple = "le32-unknown-nacl"
+
+%ac = type { i8*, i32 }
+
+@0 = constant [9 x i8] c"func %s\0A\00"
+@1 = constant [4 x i8] c"foo\00"
+@2 = constant [9 x i8] c"main %s\0A\00"
+
+declare void @llvm.trap() noreturn nounwind
+
+define void @direct(%ac) {
+entry:
+ %str = alloca %ac
+ store %ac %0, %ac* %str
+ %1 = getelementptr inbounds %ac* %str, i32 0, i32 0
+ %2 = load i8** %1
+ call void (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @0, i32 0, i32 0), i8* %2)
+ ret void
+}
+
+declare void @printf(i8*, ...)
+
+define i32 @main() {
+entry:
+ %str = alloca %ac
+ store %ac { i8* getelementptr inbounds ([4 x i8]* @1, i32 0, i32 0), i32 3 }, %ac* %str
+ %0 = getelementptr inbounds %ac* %str, i32 0, i32 0
+ %1 = load i8** %0
+ call void (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @2, i32 0, i32 0), i8* %1)
+ %2 = load %ac* %str
+ call void @direct(%ac %2)
+ ret i32 0
+}
+
diff --git a/tests/cases/structinparam.txt b/tests/cases/structinparam.txt
new file mode 100644
index 00000000..785191e7
--- /dev/null
+++ b/tests/cases/structinparam.txt
@@ -0,0 +1,2 @@
+main foo
+func foo
diff --git a/tests/emscripten_get_now.cpp b/tests/emscripten_get_now.cpp
new file mode 100644
index 00000000..17aa7d32
--- /dev/null
+++ b/tests/emscripten_get_now.cpp
@@ -0,0 +1,46 @@
+#include <stdio.h>
+#include "emscripten.h"
+
+#ifndef REPORT_RESULT
+// To be able to run this test outside the browser harness in node.js/spidermonkey:
+#define REPORT_RESULT int dummy
+#endif
+
+int result = 0;
+
+int main() {
+ // This code tests three things:
+ // a) Calling emscripten_get_now(), time actually proceeds.
+ // b) Values returned by emscripten_get_now() are strictly nondecreasing.
+ // c) emscripten_get_now() is able to return sub-millisecond precision timer values.
+ bool detected_good_timer_precision = false;
+ float smallest_delta = 0.f;
+ for(int x = 0; x < 1000; ++x) { // Have several attempts to find a good small delta, i.e. give time to JS engine to warm up the code and so on.
+ float t = emscripten_get_now();
+ float t2 = emscripten_get_now();
+ for(int i = 0; i < 100 && t == t2; ++i) {
+ t2 = emscripten_get_now();
+ }
+
+ if (t2 < t && t2 - t < 1000.f) { // Timer must be monotonous.
+ printf("Timer is not monotonous!\\n");
+ smallest_delta = t2 - t;
+ break;
+ }
+ if (t2 > t && t2 - t < 0.7f) { // Must pass less than a millisecond between two calls.
+ detected_good_timer_precision = true;
+ smallest_delta = t2 - t;
+ break;
+ }
+ }
+
+ if (detected_good_timer_precision) {
+ printf("Timer resolution is good. (%f msecs)\\n", smallest_delta);
+ result = 1;
+ } else {
+ printf("Error: Bad timer precision: Smallest timer delta: %f msecs\\n", smallest_delta);
+ result = 0;
+ }
+ REPORT_RESULT();
+ return 0;
+}
diff --git a/tests/file_db.cpp b/tests/file_db.cpp
new file mode 100644
index 00000000..ebb3bb30
--- /dev/null
+++ b/tests/file_db.cpp
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <emscripten.h>
+
+void later(void *) {}
+
+int main() {
+#if FIRST
+ FILE *f = fopen("waka.txt", "w");
+ fputc('a', f);
+ fputc('z', f);
+ fclose(f);
+
+ EM_ASM(
+ FS.saveFilesToDB(['waka.txt', 'moar.txt'], function() {
+ Module.print('save ok');
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', 'http://localhost:8888/report_result?1');
+ xhr.send();
+ setTimeout(function() { window.close() }, 1000);
+ }, function(e) {
+ abort('saving should succeed ' + e);
+ });
+ );
+#else
+ EM_ASM(
+ FS.loadFilesFromDB(['waka.txt', 'moar.txt'], function() {
+ function stringy(arr) {
+ return Array.prototype.map.call(arr, function(x) { return String.fromCharCode(x) }).join('');
+ }
+ assert(stringy(FS.analyzePath('waka.txt').object.contents) == 'az');
+ var secret = stringy(FS.analyzePath('moar.txt').object.contents);
+ Module.print('load: ' + secret);
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', 'http://localhost:8888/report_result?' + secret);
+ xhr.send();
+ setTimeout(function() { window.close() }, 1000);
+ }, function() {
+ abort('loading should succeed');
+ });
+ );
+#endif
+
+ emscripten_async_call(later, NULL, 100); // keep runtime alive
+
+ return 0;
+}
+
diff --git a/tests/filesystem/src.js b/tests/filesystem/src.js
index ceea348d..dbdd4bed 100644
--- a/tests/filesystem/src.js
+++ b/tests/filesystem/src.js
@@ -1,10 +1,13 @@
+var dummy_device = FS.makedev(64, 0);
+FS.registerDevice(dummy_device, {});
+
FS.createFolder('/', 'forbidden', false, false);
FS.createFolder('/forbidden', 'test', true, true);
FS.createPath('/', 'abc/123', true, true);
FS.createPath('/', 'abc/456', true, true);
FS.createPath('/', 'def/789', true, true);
-FS.createDevice('/abc', 'deviceA', function() {}, function() {});
-FS.createDevice('/def', 'deviceB', function() {}, function() {});
+FS.mkdev('/abc/deviceA', 0666, dummy_device);
+FS.mkdev('/def/deviceB', 0666, dummy_device);
FS.createLink('/abc', 'localLink', '123', true, true);
FS.createLink('/abc', 'rootLink', '/', true, true);
FS.createLink('/abc', 'relativeLink', '../def', true, true);
diff --git a/tests/module/test_stdin.c b/tests/module/test_stdin.c
new file mode 100644
index 00000000..4838d466
--- /dev/null
+++ b/tests/module/test_stdin.c
@@ -0,0 +1,57 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#if EMSCRIPTEN
+#include <emscripten.h>
+#endif
+
+int line = 0;
+
+void main_loop(void *arg)
+{
+ char str[10] = {0};
+ int ret;
+
+ errno = 0;
+ while (errno != EAGAIN) {
+ if (line == 0) {
+ ret = fgetc(stdin);
+ if (ret != EOF) putc(ret, stdout);
+ if (ret == '\n') line++;
+ } else if (line > 0) {
+ ret = scanf("%10s", str);
+ if (ret > 0) puts(str);
+ }
+
+ if (ferror(stdin) && errno != EAGAIN) {
+ puts("error");
+ exit(EXIT_FAILURE);
+ }
+
+ if (feof(stdin)) {
+ puts("eof");
+ exit(EXIT_SUCCESS);
+ }
+
+ clearerr(stdin);
+ }
+}
+
+int main(int argc, char const *argv[])
+{
+ fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
+
+ // SM shell doesn't implement an event loop and therefor doesn't support
+ // emscripten_set_main_loop. However, its stdin reads are sync so it
+ // should exit out after calling main_loop once.
+ main_loop(NULL);
+
+#if EMSCRIPTEN
+ emscripten_set_main_loop(main_loop, 60, 0);
+#else
+ while (1) main_loop(NULL); sleep(1);
+#endif
+ return 0;
+} \ No newline at end of file
diff --git a/tests/msvc10/glbook_10_MultiTexture.vcxproj b/tests/msvc10/glbook_10_MultiTexture.vcxproj
index b59fda0a..a831f351 100644
--- a/tests/msvc10/glbook_10_MultiTexture.vcxproj
+++ b/tests/msvc10/glbook_10_MultiTexture.vcxproj
@@ -82,12 +82,12 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/tests/msvc10/glbook_11_Multisample.vcxproj b/tests/msvc10/glbook_11_Multisample.vcxproj
index ae5170be..47d5fb4a 100644
--- a/tests/msvc10/glbook_11_Multisample.vcxproj
+++ b/tests/msvc10/glbook_11_Multisample.vcxproj
@@ -82,12 +82,12 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/tests/msvc10/glbook_11_Stencil_Test.vcxproj b/tests/msvc10/glbook_11_Stencil_Test.vcxproj
index d72d7fa6..3a541128 100644
--- a/tests/msvc10/glbook_11_Stencil_Test.vcxproj
+++ b/tests/msvc10/glbook_11_Stencil_Test.vcxproj
@@ -82,12 +82,12 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/tests/msvc10/glbook_13_ParticleSystem.vcxproj b/tests/msvc10/glbook_13_ParticleSystem.vcxproj
index 458d76fa..c18e17ff 100644
--- a/tests/msvc10/glbook_13_ParticleSystem.vcxproj
+++ b/tests/msvc10/glbook_13_ParticleSystem.vcxproj
@@ -82,12 +82,12 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/tests/msvc10/glbook_15_Hello_Triangle_KD.vcxproj b/tests/msvc10/glbook_15_Hello_Triangle_KD.vcxproj
index 654164b3..489628f5 100644
--- a/tests/msvc10/glbook_15_Hello_Triangle_KD.vcxproj
+++ b/tests/msvc10/glbook_15_Hello_Triangle_KD.vcxproj
@@ -82,12 +82,12 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/tests/msvc10/glbook_2_Hello_Triangle.vcxproj b/tests/msvc10/glbook_2_Hello_Triangle.vcxproj
index b992294d..34de0780 100644
--- a/tests/msvc10/glbook_2_Hello_Triangle.vcxproj
+++ b/tests/msvc10/glbook_2_Hello_Triangle.vcxproj
@@ -92,12 +92,12 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/tests/msvc10/glbook_8_Simple_VertexShader.vcxproj b/tests/msvc10/glbook_8_Simple_VertexShader.vcxproj
index fb01c1da..19442df9 100644
--- a/tests/msvc10/glbook_8_Simple_VertexShader.vcxproj
+++ b/tests/msvc10/glbook_8_Simple_VertexShader.vcxproj
@@ -82,12 +82,12 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/tests/msvc10/glbook_9_MipMap2D.vcxproj b/tests/msvc10/glbook_9_MipMap2D.vcxproj
index 1d747d1d..af0e072b 100644
--- a/tests/msvc10/glbook_9_MipMap2D.vcxproj
+++ b/tests/msvc10/glbook_9_MipMap2D.vcxproj
@@ -82,12 +82,12 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/tests/msvc10/glbook_9_Simple_Texture2D.vcxproj b/tests/msvc10/glbook_9_Simple_Texture2D.vcxproj
index d9232e5d..09ff3e1e 100644
--- a/tests/msvc10/glbook_9_Simple_Texture2D.vcxproj
+++ b/tests/msvc10/glbook_9_Simple_Texture2D.vcxproj
@@ -82,12 +82,12 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/tests/msvc10/glbook_9_Simple_TextureCubemap.vcxproj b/tests/msvc10/glbook_9_Simple_TextureCubemap.vcxproj
index c5c6ee1b..d89da1c7 100644
--- a/tests/msvc10/glbook_9_Simple_TextureCubemap.vcxproj
+++ b/tests/msvc10/glbook_9_Simple_TextureCubemap.vcxproj
@@ -82,12 +82,12 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/tests/msvc10/glbook_9_TextureWrap.vcxproj b/tests/msvc10/glbook_9_TextureWrap.vcxproj
index 6cfbb0c8..54f51e26 100644
--- a/tests/msvc10/glbook_9_TextureWrap.vcxproj
+++ b/tests/msvc10/glbook_9_TextureWrap.vcxproj
@@ -82,12 +82,12 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/tests/termios/test_tcgetattr.c b/tests/termios/test_tcgetattr.c
new file mode 100644
index 00000000..2b3780ee
--- /dev/null
+++ b/tests/termios/test_tcgetattr.c
@@ -0,0 +1,61 @@
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+static void create_file(const char *path, const char *buffer, int mode) {
+ int fd = open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
+ assert(fd >= 0);
+
+ int err = write(fd, buffer, sizeof(char) * strlen(buffer));
+ assert(err == (sizeof(char) * strlen(buffer)));
+
+ close(fd);
+}
+
+void setup() {
+ create_file("test.txt", "abcdefg", 0666);
+}
+
+void cleanup() {
+ unlink("test.txt");
+}
+
+void test() {
+ struct termios tc;
+ int ret;
+ int fd;
+
+ fd = open("test.txt", O_RDONLY);
+
+ ret = tcgetattr(fd, &tc);
+ assert(ret == -1);
+ assert(errno = ENOTTY);
+
+ ret = tcgetattr(STDIN_FILENO, &tc);
+ assert(!ret);
+
+ ret = tcsetattr(fd, 0, &tc);
+ assert(ret == -1);
+ assert(errno = ENOTTY);
+
+ ret = tcsetattr(STDIN_FILENO, 0, &tc);
+ assert(!ret);
+
+ close(fd);
+
+ puts("success");
+}
+
+int main() {
+ atexit(cleanup);
+ signal(SIGABRT, cleanup);
+ setup();
+ test();
+ return EXIT_SUCCESS;
+}
diff --git a/tests/test_browser.py b/tests/test_browser.py
index 1c9cbfad..a0c4dceb 100644
--- a/tests/test_browser.py
+++ b/tests/test_browser.py
@@ -794,6 +794,20 @@ If manually bisecting:
def test_glut_touchevents(self):
self.btest('glut_touchevents.c', '1')
+ def test_emscripten_get_now(self):
+ self.btest('emscripten_get_now.cpp', '1')
+
+ def test_file_db(self):
+ secret = str(time.time())
+ open('moar.txt', 'w').write(secret)
+ self.btest('file_db.cpp', '1', args=['--preload-file', 'moar.txt', '-DFIRST'])
+ shutil.copyfile('test.html', 'first.html')
+ self.btest('file_db.cpp', secret)
+ shutil.copyfile('test.html', 'second.html')
+ open('moar.txt', 'w').write('aliantha')
+ self.btest('file_db.cpp', secret, args=['--preload-file', 'moar.txt']) # even with a file there, we load over it
+ shutil.move('test.html', 'third.html')
+
def test_sdl_pumpevents(self):
# key events should be detected using SDL_PumpEvents
open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
diff --git a/tests/test_core.py b/tests/test_core.py
index 7c5b651f..6d15da1e 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -3734,6 +3734,13 @@ def process(filename):
Settings.EXPORT_ALL = 1
self.do_run(src, 'hello world!\n*100*\n*fivesix*\nmann\n', post_build=check)
+ def test_emscripten_get_now(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('requires ta2')
+
+ if self.run_name == 'o2':
+ self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage
+ 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: return self.skip('asm does not support random code, TODO: something that works in asm')
src = r'''
@@ -4670,6 +4677,10 @@ The current type of b is: 9
expected = open(path_from_root('tests', 'pthread', 'specific.c.txt'), 'r').read()
self.do_run(src, expected, force_c=True)
+ def test_tcgetattr(self):
+ src = open(path_from_root('tests', 'termios', 'test_tcgetattr.c'), 'r').read()
+ self.do_run(src, 'success', force_c=True)
+
def test_time(self):
# XXX Not sure what the right output is here. Looks like the test started failing with daylight savings changes. Modified it to pass again.
src = open(path_from_root('tests', 'time', 'src.c'), 'r').read()
@@ -6977,8 +6988,11 @@ def process(filename):
src = open(filename, 'r').read().replace(
'// {{PRE_RUN_ADDITIONS}}',
\'\'\'
+ var dummy_device = FS.makedev(64, 0);
+ FS.registerDevice(dummy_device, {});
+
FS.createDataFile('/', 'file', 'abcdef', true, true);
- FS.createDevice('/', 'device', function() {}, function() {});
+ FS.mkdev('/device', 0666, dummy_device);
\'\'\'
)
open(filename, 'w').write(src)
@@ -8594,7 +8608,7 @@ def process(filename):
do_test()
# some test coverage for EMCC_DEBUG 1 and 2
- if self.emcc_args and '-O2' in self.emcc_args and 'EMCC_DEBUG' not in os.environ:
+ if self.emcc_args and '-O2' in self.emcc_args and 'EMCC_DEBUG' not in os.environ and '-g' in self.emcc_args:
shutil.copyfile('src.c.o.js', 'release.js')
try:
os.environ['EMCC_DEBUG'] = '1'
@@ -8609,7 +8623,8 @@ def process(filename):
del os.environ['EMCC_DEBUG']
for debug in [1,2]:
def clean(text):
- return text.replace('\n\n', '\n').replace('\n\n', '\n').replace('\n\n', '\n').replace('\n\n', '\n').replace('\n\n', '\n').replace('{\n}', '{}')
+ text = text.replace('\n\n', '\n').replace('\n\n', '\n').replace('\n\n', '\n').replace('\n\n', '\n').replace('\n\n', '\n').replace('{\n}', '{}')
+ return '\n'.join(sorted(text.split('\n')))
self.assertIdentical(clean(open('release.js').read()), clean(open('debug%d.js' % debug).read())) # EMCC_DEBUG=1 mode must not generate different code!
print >> sys.stderr, 'debug check %d passed too' % debug
@@ -9681,7 +9696,8 @@ def process(filename):
# optimizer can deal with both types.
out_file = re.sub(' *//@.*$', '', out_file, flags=re.MULTILINE)
def clean(code):
- return code.replace('{\n}', '{}')
+ code = code.replace('{\n}', '{}')
+ return '\n'.join(sorted(code.split('\n')))
self.assertIdentical(clean(no_maps_file), clean(out_file))
map_filename = out_filename + '.map'
data = json.load(open(map_filename, 'r'))
diff --git a/tests/test_other.py b/tests/test_other.py
index a6813b07..fd1a6245 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -929,20 +929,14 @@ f.close()
self.assertContained('libf1\nlibf2\n', run_js(os.path.join(self.get_dir(), 'a.out.js')))
def test_stdin(self):
- open('main.cpp', 'w').write(r'''
-#include <stdio.h>
-int main(int argc, char const *argv[])
-{
- char str[10] = {0};
- scanf("%10s", str);
- printf("%s\n", str);
- return 0;
-}
-''')
- Building.emcc('main.cpp', output_filename='a.out.js')
- open('in.txt', 'w').write('abc')
- # node's stdin support is broken
- self.assertContained('abc', Popen(listify(SPIDERMONKEY_ENGINE) + ['a.out.js'], stdin=open('in.txt'), stdout=PIPE, stderr=PIPE).communicate()[0])
+ Building.emcc(path_from_root('tests', 'module', 'test_stdin.c'), output_filename='a.out.js')
+ open('in.txt', 'w').write('abcdef\nghijkl')
+
+ for engine in JS_ENGINES:
+ print >> sys.stderr, engine
+ if engine == NODE_JS: continue # FIXME
+ if engine == V8_ENGINE: continue # no stdin support in v8 shell
+ self.assertContained('abcdef\nghijkl\neof', run_js(os.path.join(self.get_dir(), 'a.out.js'), engine=engine, stdin=open('in.txt')))
def test_ungetc_fscanf(self):
open('main.cpp', 'w').write(r'''
diff --git a/tests/unistd/curdir.js b/tests/unistd/curdir.js
index e271b9da..75a1d2ce 100644
--- a/tests/unistd/curdir.js
+++ b/tests/unistd/curdir.js
@@ -1,4 +1,7 @@
+var dummy_device = FS.makedev(64, 0);
+FS.registerDevice(dummy_device, {});
+
FS.createDataFile('/', 'file', '', true, true);
FS.createFolder('/', 'folder', true, true);
-FS.createDevice('/', 'device', function() {}, function() {});
+FS.mkdev('/device', 0666, dummy_device);
FS.createLink('/', 'link', 'folder', true, true);
diff --git a/tests/unistd/io.c b/tests/unistd/io.c
index eeb80373..a96290ef 100644
--- a/tests/unistd/io.c
+++ b/tests/unistd/io.c
@@ -34,6 +34,19 @@ int main() {
printf("errno: %d\n\n", errno);
errno = 0;
+ int cd_ro_r = open("/createDevice-read-only", O_RDONLY);
+ printf("open read-only device from createDevice for read, errno: %d\n", errno);
+ errno = 0;
+ int cd_ro_w = open("/createDevice-read-only", O_WRONLY);
+ printf("open read-only device from createDevice for write, errno: %d\n", errno);
+ errno = 0;
+ int cd_wo_r = open("/createDevice-write-only", O_RDONLY);
+ printf("open write-only device from createDevice for read, errno: %d\n", errno);
+ errno = 0;
+ int cd_wo_w = open("/createDevice-write-only", O_WRONLY);
+ printf("open write-only device from createDevice for write, errno: %d\n\n", errno);
+ errno = 0;
+
int f = open("/file", O_RDWR);
printf("read from file: %d\n", read(f, readBuffer, sizeof readBuffer));
printf("data: %s\n", readBuffer);
diff --git a/tests/unistd/io.js b/tests/unistd/io.js
index e2e442ec..11c0da79 100644
--- a/tests/unistd/io.js
+++ b/tests/unistd/io.js
@@ -1,19 +1,52 @@
(function() {
- var devicePayload = [65, 66, 67, 68];
- FS.createDevice('/', 'device', function() {
- if (devicePayload.length) {
- return devicePayload.shift();
- } else {
- return null;
+ var major = 80;
+
+ var device = FS.makedev(major++, 0);
+ var device_ops = {
+ open: function(stream) {
+ stream.payload = [65, 66, 67, 68];
+ },
+ read: function(stream, buffer, offset, length, pos) {
+ var bytesRead = 0;
+ for (var i = 0; i < length; i++) {
+ if (stream.payload.length) {
+ bytesRead++;
+ buffer[offset+i] = stream.payload.shift();
+ } else {
+ break;
+ }
+ }
+ return bytesRead;
+ },
+ write: function(stream, buffer, offset, length, pos) {
+ for (var i = 0; i < length; i++) {
+ Module.print("TO DEVICE: " + buffer[offset+i]);
+ }
+ return i;
}
- }, function(arg) {
- Module.print("TO DEVICE: " + arg);
- });
- FS.createDevice('/', 'broken-device', function() {
- throw new Error('Broken device input.');
- }, function(arg) {
- throw new Error('Broken device output.');
- });
+ };
+ FS.registerDevice(device, device_ops);
+
+ FS.mkdev('/device', 0666, device);
+
+ var broken_device = FS.makedev(major++, 0);
+ var broken_device_ops = {
+ read: function(stream, buffer, offset, length, pos) {
+ throw new FS.ErrnoError(ERRNO_CODES.EIO);
+ },
+ write: function(stream, buffer, offset, length, pos) {
+ throw new FS.ErrnoError(ERRNO_CODES.EIO);
+ }
+ };
+ FS.registerDevice(broken_device, broken_device_ops);
+
+ FS.mkdev('/broken-device', 0666, broken_device);
+
+ // NB: These are meant to test FS.createDevice specifically,
+ // and as such do not use registerDevice/mkdev
+ FS.createDevice('/', 'createDevice-read-only', function() {});
+ FS.createDevice('/', 'createDevice-write-only', null, function() {});
+
FS.createDataFile('/', 'file', '1234567890', true, true);
FS.createFolder('/', 'folder', true, true);
})();
diff --git a/tests/unistd/io.out b/tests/unistd/io.out
index 3061b94e..037d0c34 100644
--- a/tests/unistd/io.out
+++ b/tests/unistd/io.out
@@ -22,6 +22,11 @@ TO DEVICE: 0
write to device: 8
errno: 0
+open read-only device from createDevice for read, errno: 0
+open read-only device from createDevice for write, errno: 13
+open write-only device from createDevice for read, errno: 13
+open write-only device from createDevice for write, errno: 0
+
read from file: 10
data: 1234567890
errno: 0
diff --git a/tools/file_packager.py b/tools/file_packager.py
index bb62e905..8f0f8be8 100644
--- a/tools/file_packager.py
+++ b/tools/file_packager.py
@@ -344,14 +344,7 @@ if has_preloaded:
},
send: function() {},
onload: function() {
- var data = this.byteArray.subarray(this.start, this.end);
- var size = this.end - this.start;
- var ptr = Module['_malloc'](size); // XXX leaked if a preload plugin replaces with new data
- Module['HEAPU8'].set(data, ptr);
- var arrayBuffer = Module['HEAPU8'].subarray(ptr, ptr + size);
- assert(arrayBuffer, 'Loading file ' + name + ' failed');
- var byteArray = !arrayBuffer.subarray ? new Uint8Array(arrayBuffer) : arrayBuffer;
-
+ var byteArray = this.byteArray.subarray(this.start, this.end);
if (this.crunched) {
var ddsHeader = byteArray.subarray(0, 128);
var that = this;
@@ -367,7 +360,7 @@ if has_preloaded:
},
finish: function(byteArray) {
var that = this;
- Module['FS_createPreloadedFile'](PATH.dirname(this.name), PATH.basename(this.name), byteArray, true, true, function() {
+ Module['FS_createPreloadedFile'](this.name, null, byteArray, true, true, function() {
Module['removeRunDependency']('fp ' + that.name);
}, function() {
if (that.audio) {
@@ -375,7 +368,7 @@ if has_preloaded:
} else {
Runtime.warn('Preloading file ' + that.name + ' failed');
}
- });
+ }, false, true); // canOwn this data in the filesystem, it is a slide into the heap that will never change
this.requests[this.name] = null;
},
};
@@ -419,7 +412,12 @@ for file_ in data_files:
if has_preloaded:
# Get the big archive and split it up
- use_data = ' DataRequest.prototype.byteArray = byteArray;\n'
+ 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);
+'''
for file_ in data_files:
if file_['mode'] == 'preload':
use_data += ' DataRequest.prototype.requests["%s"].onload();\n' % (file_['dstpath'])
diff --git a/tools/find_bigfuncs.py b/tools/find_bigfuncs.py
index 79136343..c8e29833 100644
--- a/tools/find_bigfuncs.py
+++ b/tools/find_bigfuncs.py
@@ -18,6 +18,6 @@ for line in open(filename):
size = i - start
data.append([curr, size])
curr = None
-data.sort(lambda x, y: x[1] - y[1])
+#data.sort(lambda x, y: x[1] - y[1])
print ''.join(['%6d : %s' % (x[1], x[0]) for x in data])
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 9a5104bf..b42164f9 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -135,6 +135,7 @@ var ASSIGN_OR_ALTER = set('assign', 'unary-postfix', 'unary-prefix');
var CONTROL_FLOW = set('do', 'while', 'for', 'if', 'switch');
var NAME_OR_NUM = set('name', 'num');
var ASSOCIATIVE_BINARIES = set('+', '*', '|', '&', '^');
+var ALTER_FLOW = set('break', 'continue', 'return');
var BREAK_CAPTURERS = set('do', 'while', 'for', 'switch');
var CONTINUE_CAPTURERS = LOOP;
@@ -3070,10 +3071,10 @@ function outline(ast) {
currSize += size;
if (!isIf) {
var last = part.body;
- last = last[stats.length-1];
+ last = last[last.length-1];
if (last && last[0] === 'block') last = last[1][last[1].length-1];
if (last && last[0] === 'stat') last = last[1];
- force = !last || last[0] !== 'break';
+ force = !last || !(last[0] in ALTER_FLOW);
}
});
assert(currSize);
@@ -3487,7 +3488,7 @@ function outline(ast) {
}
}
outliningParents[newIdent] = func[1];
- printErr('performed outline ' + [func[1], newIdent, 'code sizes (pre/post):', originalCodeSize, measureSize(code), 'overhead (w/r):', setSize(setSub(codeInfo.writes, owned)), setSize(setSub(codeInfo.reads, owned)), ' owned: ', setSize(owned), ' left: ', setSize(asmData.vars), setSize(asmData.params), ' loopsDepth: ', loops]);
+ printErr('performed outline ' + [func[1], newIdent, 'pre size', originalCodeSize, 'resulting size', measureSize(code), 'overhead (w/r):', setSize(setSub(codeInfo.writes, owned)), setSize(setSub(codeInfo.reads, owned)), ' owned: ', setSize(owned), ' left: ', setSize(asmData.vars), setSize(asmData.params), ' loopsDepth: ', loops]);
calculateThreshold(func, asmData);
return [newFunc];
}
@@ -3633,6 +3634,8 @@ function outline(ast) {
var maxTotalFunctions = Infinity; // debugging tool
+ printErr('\n');
+
var more = true;
while (more) {
more = false;
@@ -3691,7 +3694,8 @@ function outline(ast) {
}
}
}
- printErr('... resulting size of ' + func[1] + ' is ' + measureSize(func));
+ ret.push(func);
+ printErr('... resulting sizes of ' + func[1] + ' is ' + ret.map(measureSize) + '\n');
}
denormalizeAsm(func, asmData);
});
diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py
index 5d7dc562..a11da7f0 100644
--- a/tools/js_optimizer.py
+++ b/tools/js_optimizer.py
@@ -205,23 +205,26 @@ EMSCRIPTEN_FUNCS();
pre = ''
post = ''
- # Pick where to split into chunks, so that (1) they do not oom in node/uglify, and (2) we can run them in parallel
- # If we have metadata, we split only the generated code, and save the pre and post on the side (and do not optimize them)
- parts = map(lambda part: part, js.split('\n}\n'))
- funcs = []
- for i in range(len(parts)):
- func = parts[i]
- if i < len(parts)-1: func += '\n}\n' # last part needs no }
- m = func_sig.search(func)
- if m:
- ident = m.group(2)
- else:
- if know_generated: continue # ignore whitespace
- ident = 'anon_%d' % i
- assert ident
- funcs.append((ident, func))
- parts = None
+ def split_funcs(js):
+ # Pick where to split into chunks, so that (1) they do not oom in node/uglify, and (2) we can run them in parallel
+ # If we have metadata, we split only the generated code, and save the pre and post on the side (and do not optimize them)
+ parts = map(lambda part: part, js.split('\n}\n'))
+ funcs = []
+ for i in range(len(parts)):
+ func = parts[i]
+ if i < len(parts)-1: func += '\n}\n' # last part needs no }
+ m = func_sig.search(func)
+ if m:
+ ident = m.group(2)
+ else:
+ if know_generated: continue # ignore whitespace
+ ident = 'anon_%d' % i
+ assert ident
+ funcs.append((ident, func))
+ return funcs
+
total_size = len(js)
+ funcs = split_funcs(js)
js = None
if 'last' in passes and len(funcs) > 0:
@@ -235,6 +238,7 @@ EMSCRIPTEN_FUNCS();
chunk_size = min(MAX_CHUNK_SIZE, max(MIN_CHUNK_SIZE, total_size / intended_num_chunks))
chunks = shared.chunkify(funcs, chunk_size, jcache.get_cachename('jsopt') if jcache else None)
+ funcs = None
if jcache:
# load chunks from cache where we can # TODO: ignore small chunks
@@ -324,9 +328,25 @@ EMSCRIPTEN_FUNCS();
filename += '.jo.js'
f = open(filename, 'w')
f.write(pre);
+ pre = None
+
+ # sort functions by size, to make diffing easier and to improve aot times
+ funcses = []
for out_file in filenames:
- f.write(open(out_file).read())
- f.write('\n')
+ funcses.append(split_funcs(open(out_file).read()))
+ funcs = [item for sublist in funcses for item in sublist]
+ funcses = None
+ def sorter(x, y):
+ diff = len(y[1]) - len(x[1])
+ if diff != 0: return diff
+ if x[0] < y[0]: return 1
+ elif x[0] > y[0]: return -1
+ return 0
+ funcs.sort(sorter)
+ for func in funcs:
+ f.write(func[1])
+ funcs = None
+ f.write('\n')
if jcache:
for cached in cached_outputs:
f.write(cached); # TODO: preserve order
diff --git a/tools/jsrun.py b/tools/jsrun.py
index 571e9cee..91038f6e 100644
--- a/tools/jsrun.py
+++ b/tools/jsrun.py
@@ -12,13 +12,14 @@ def timeout_run(proc, timeout, note='unnamed process', full_output=False):
out = proc.communicate()
return '\n'.join(out) if full_output else out[0]
-def run_js(filename, engine=None, args=[], check_timeout=False, stdout=PIPE, stderr=None, cwd=None, full_output=False):
+def run_js(filename, engine=None, args=[], check_timeout=False, stdin=None, stdout=PIPE, stderr=None, cwd=None, full_output=False):
if type(engine) is not list:
engine = [engine]
command = engine + [filename] + (['--'] if 'd8' in engine[0] or 'jsc' in engine[0] else []) + args
return timeout_run(
Popen(
command,
+ stdin=stdin,
stdout=stdout,
stderr=stderr,
cwd=cwd),
diff --git a/tools/test-js-optimizer-asm-outline1-output.js b/tools/test-js-optimizer-asm-outline1-output.js
index 895004d8..612da16a 100644
--- a/tools/test-js-optimizer-asm-outline1-output.js
+++ b/tools/test-js-optimizer-asm-outline1-output.js
@@ -348,6 +348,15 @@ function switchh() {
HEAP32[sp + 44 >> 2] = 0;
switchh$2(sp);
helper$0 = HEAP32[sp + 8 >> 2] | 0;
+ tempValue = HEAP32[sp + 40 >> 2] | 0;
+ tempInt = HEAP32[sp + 44 >> 2] | 0;
+ tempDouble = +HEAPF32[sp + 44 >> 2];
+ HEAP32[sp + 40 >> 2] = 0;
+ HEAP32[sp + 44 >> 2] = 0;
+ if ((tempValue | 0) == 5) {
+ STACKTOP = sp;
+ return;
+ }
HEAP32[sp + 8 >> 2] = helper$0;
HEAP32[sp + 16 >> 2] = helper$1;
HEAP32[sp + 32 >> 2] = 0;
@@ -749,36 +758,39 @@ function switchh$2(sp) {
var helper$0 = 0, helper$1 = 0;
helper$0 = HEAP32[sp + 8 >> 2] | 0;
helper$1 = HEAP32[sp + 16 >> 2] | 0;
- if (helper$0) {
- helper$0 = 0;
- switch (helper$1 | 0) {
- case 1:
- {
- f(1);
- g();
- break;
- }
- default:
- {
- helper$0 = 1;
+ OL : do {
+ if (helper$0) {
+ helper$0 = 0;
+ switch (helper$1 | 0) {
+ case 1:
+ {
+ f(1);
+ g();
+ HEAP32[sp + 40 >> 2] = 5;
+ break OL;
+ }
+ default:
+ {
+ helper$0 = 1;
+ }
}
}
- }
- if (helper$0) {
- helper$0 = 0;
- switch (helper$1 | 0) {
- case 2:
- {
- f(2);
- g();
- break;
- }
- default:
- {
- helper$0 = 1;
+ if (helper$0) {
+ helper$0 = 0;
+ switch (helper$1 | 0) {
+ case 2:
+ {
+ f(2);
+ g();
+ break;
+ }
+ default:
+ {
+ helper$0 = 1;
+ }
}
}
- }
+ } while (0);
HEAP32[sp + 8 >> 2] = helper$0;
}
diff --git a/tools/test-js-optimizer-asm-outline1.js b/tools/test-js-optimizer-asm-outline1.js
index 3c454182..4282ec8e 100644
--- a/tools/test-js-optimizer-asm-outline1.js
+++ b/tools/test-js-optimizer-asm-outline1.js
@@ -269,7 +269,7 @@ function switchh() {
case 1: {
f(1);
g();
- break;
+ return;
}
case 2: {
f(2);