aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog38
-rw-r--r--cmake/Modules/FindOpenAL.cmake26
-rw-r--r--cmake/Platform/Emscripten.cmake7
-rwxr-xr-xemcc15
-rw-r--r--src/intertyper.js3
-rw-r--r--src/library.js55
-rw-r--r--src/library_browser.js4
-rw-r--r--src/library_sdl.js2
-rw-r--r--src/preamble.js2
-rw-r--r--src/runtime.js12
-rw-r--r--system/include/emscripten/emscripten.h31
-rw-r--r--tests/freealut/CMakeLists.txt55
-rwxr-xr-xtests/runner.py24
-rw-r--r--tests/sockets/test_sockets_echo_server.c9
-rw-r--r--tests/test_browser.py115
-rw-r--r--tests/test_core.py12
-rw-r--r--tests/test_sanity.py2
-rw-r--r--tests/test_sockets.py4
-rw-r--r--third_party/lzma.js/doit.bat4
-rw-r--r--tools/settings_template_readonly.py2
-rw-r--r--tools/split.py34
21 files changed, 331 insertions, 125 deletions
diff --git a/ChangeLog b/ChangeLog
index cca1b833..94a24675 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,44 @@ To browse or download snapshots of old tagged versions, visit https://github.com
Not all changes are documented here. In particular, new features, user-oriented fixes, options, command-line parameters, usage changes, deprecations, significant internal modifications and optimizations etc. generally deserve a mention. To examine the full set of changes between versions, visit the link to full changeset diff at the end of each section.
+Current trunk code
+------------------
+ - To see a list of commits that in the active development branch 'incoming', which have not yet been packaged in a release, see
+ https://github.com/kripken/emscripten/compare/1.7.5...incoming
+
+v1.7.5: 11/13/2013
+------------------
+ - Fix issues with the built-in C++ function name demangler.
+ - Full list of changes: https://github.com/kripken/emscripten/compare/1.7.4...1.7.5
+
+v1.7.4: 11/12/2013
+------------------
+ - Fixed issues with BSD sockets code and SDL joystick implementation.
+ - Full list of changes: https://github.com/kripken/emscripten/compare/1.7.3...1.7.4
+
+v1.7.3: 11/12/2013
+------------------
+ - Added support for generating single-precision floating point instructions.
+ - For more information, read https://blog.mozilla.org/javascript/2013/11/07/efficient-float32-arithmetic-in-javascript/
+ - Made GLES2 support library more spec-conformant by throwing fewer exceptions on errors. Be sure to build with -s GL_ASSERTIONS=1, remember to use glGetError() and check the browser console to best detect WebGL rendering errors.
+ - Converted return value of emscripten_get_now() from float to double, to not lose precision in the function call.
+ - Added support for joysticks in SDL via the Gamepad API
+ - Full list of changes: https://github.com/kripken/emscripten/compare/1.7.2...1.7.3
+
+v1.7.2: 11/9/2013
+------------------
+ - The compiler now always generates a .js file that contains the generated source code even when compiling to a .html file.
+ - Read https://groups.google.com/forum/#!topic/emscripten-discuss/EuHMwqdSsEs
+ - Implemented depth+stencil buffer choosing behavior in GLUT, SDL and GLFW.
+ - Fixed memory leaks generated by glGetString and eglGetString.
+ - Greatly optimized startup times when virtual filesystems with a large amount of files in them.
+ - Added some support for SIMD generated by LLVM.
+ - Fixed some mappings with SDL keyboard codes.
+ - Added a new command line parameter --no-heap-copy to compiler and file packager that can be used to optimize VFS memory usage at startup.
+ - Updated libcxx to revision 194185, 2013-11-07.
+ - Improvements to various library support.
+ - Full list of changes: https://github.com/kripken/emscripten/compare/1.7.1...1.7.2
+
v1.7.1: 10/24/2013
------------------
- Remove old call to Runtime.warn in file packager code
diff --git a/cmake/Modules/FindOpenAL.cmake b/cmake/Modules/FindOpenAL.cmake
new file mode 100644
index 00000000..3170966d
--- /dev/null
+++ b/cmake/Modules/FindOpenAL.cmake
@@ -0,0 +1,26 @@
+# Locate OpenAL
+# This module defines
+# OPENAL_LIBRARY
+# OPENAL_FOUND, if false, do not try to link to OpenAL
+# OPENAL_INCLUDE_DIR, where to find the headers
+
+# The implementation is based on the standard FindOpenAL.cmake provided with CMake,
+# but customized for targeting Emscripten only.
+
+if (NOT OPENAL_FOUND)
+ SET(OPENAL_FOUND TRUE)
+
+ # For Emscripten-compiled apps in the test suite (test_alut), this is expected...
+ SET(OPENAL_INCLUDE_DIR "${EMSCRIPTEN_ROOT_PATH}/system/include")
+ # ... but the stock FindOpenAL.cmake would have returned this.
+ #SET(OPENAL_INCLUDE_DIR "${EMSCRIPTEN_ROOT_PATH}/system/include/AL")
+
+ # No library to link against for OpenAL, this is picked up automatically by library_openal.js,
+ # but need to report something, or CMake thinks we failed in the search.
+ SET(OPENAL_LIBRARY "nul")
+ SET(OPENAL_LIB "")
+
+ set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${EMSCRIPTEN_ROOT_PATH}/system/include" "${EMSCRIPTEN_ROOT_PATH}/system/include/AL")
+
+ MARK_AS_ADVANCED(OPENAL_LIBRARY OPENAL_INCLUDE_DIR)
+endif()
diff --git a/cmake/Platform/Emscripten.cmake b/cmake/Platform/Emscripten.cmake
index e1e54ccf..c30632ca 100644
--- a/cmake/Platform/Emscripten.cmake
+++ b/cmake/Platform/Emscripten.cmake
@@ -44,9 +44,10 @@ endif()
# Normalize, convert Windows backslashes to forward slashes or CMake will crash.
get_filename_component(EMSCRIPTEN_ROOT_PATH "${EMSCRIPTEN_ROOT_PATH}" ABSOLUTE)
-if ("${CMAKE_MODULE_PATH}" STREQUAL "")
- set(CMAKE_MODULE_PATH "${EMSCRIPTEN_ROOT_PATH}/cmake")
+if (NOT CMAKE_MODULE_PATH)
+ set(CMAKE_MODULE_PATH "")
endif()
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${EMSCRIPTEN_ROOT_PATH}/cmake/Modules")
set(CMAKE_FIND_ROOT_PATH "${EMSCRIPTEN_ROOT_PATH}/cmake")
@@ -82,6 +83,8 @@ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+set(CMAKE_SYSTEM_INCLUDE_PATH "${EMSCRIPTEN_ROOT_PATH}/system/include")
+
# We would prefer to specify a standard set of Clang+Emscripten-friendly common convention for suffix files, especially for CMake executable files,
# but if these are adjusted, ${CMAKE_ROOT}/Modules/CheckIncludeFile.cmake will fail, since it depends on being able to compile output files with predefined names.
#SET(CMAKE_LINK_LIBRARY_SUFFIX "")
diff --git a/emcc b/emcc
index 3ac1975f..6a483a39 100755
--- a/emcc
+++ b/emcc
@@ -50,7 +50,7 @@ emcc can be influenced by a few environment variables:
import os, sys, shutil, tempfile, subprocess, shlex, time, re, logging
from subprocess import PIPE, STDOUT
from tools import shared, jsrun
-from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename
+from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename, WINDOWS
from tools.response_file import read_response_file
CXX_SUFFIXES = ('.cpp', '.cxx', '.cc')
@@ -887,8 +887,17 @@ try:
check_bad_eq(newargs[i])
parts = newargs[i+1].split(',')
assert len(parts) == 3, '--compression requires specifying native_encoder,js_decoder,js_name - see emcc --help. got: %s' % newargs[i+1]
- Compression.encoder = parts[0]
- Compression.decoder = parts[1]
+ def locate(tool):
+ if WINDOWS:
+ if os.path.exists(tool+'.exe'):
+ return tool+'.exe'
+ if os.path.exists(tool+'.bat'):
+ return tool+'.bat'
+ if os.path.exists(tool+'.cmd'):
+ return tool+'.cmd'
+ return tool
+ Compression.encoder = locate(parts[0])
+ Compression.decoder = locate(parts[1])
Compression.js_name = parts[2]
assert os.path.exists(Compression.encoder), 'native encoder %s does not exist' % Compression.encoder
assert os.path.exists(Compression.decoder), 'js decoder %s does not exist' % Compression.decoder
diff --git a/src/intertyper.js b/src/intertyper.js
index f92a04db..940c677f 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -660,9 +660,10 @@ function intertyper(lines, sidePass, baseLineNums) {
var tokensLeft = item.tokens.slice(2);
item.ident = eatLLVMIdent(tokensLeft);
if (item.ident == 'asm') {
+ warnOnce('inline JavaScript using asm() has some oddities due to how gcc asm() syntax works. use EM_ASM where possible (see emscripten.h)');
if (ASM_JS) {
Types.hasInlineJS = true;
- warnOnce('inline JavaScript (asm, EM_ASM) will cause the code to no longer fall in the asm.js subset of JavaScript, which can reduce performance - consider using emscripten_run_script');
+ warnOnce('inline JavaScript using asm() will cause the code to no longer fall in the asm.js subset of JavaScript, which can reduce performance - consider using emscripten_run_script');
}
assert(TARGET_LE32, 'inline js is only supported in le32');
// Inline assembly is just JavaScript that we paste into the code
diff --git a/src/library.js b/src/library.js
index 6d821bfc..a5380c3a 100644
--- a/src/library.js
+++ b/src/library.js
@@ -3193,7 +3193,7 @@ LibraryManager.library = {
}
}
if (!finalBase) finalBase = 10;
- start = str;
+ var start = str;
// Get digits.
var chr;
@@ -6122,7 +6122,7 @@ LibraryManager.library = {
clock_gettime: function(clk_id, tp) {
// int clock_gettime(clockid_t clk_id, struct timespec *tp);
var now;
- if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) {
+ if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) {
now = Date.now();
} else {
now = _emscripten_get_now();
@@ -6136,10 +6136,17 @@ LibraryManager.library = {
// Nothing.
return 0;
},
+ clock_getres__deps: ['emscripten_get_now_res'],
clock_getres: function(clk_id, res) {
// int clock_getres(clockid_t clk_id, struct timespec *res);
+ var nsec;
+ if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) {
+ nsec = 1000 * 1000;
+ } else {
+ nsec = _emscripten_get_now_res();
+ }
{{{ makeSetValue('res', C_STRUCTS.timespec.tv_sec, '1', 'i32') }}}
- {{{ makeSetValue('res', C_STRUCTS.timespec.tv_nsec, '1000 * 1000', 'i32') }}} // resolution is milliseconds
+ {{{ makeSetValue('res', C_STRUCTS.timespec.tv_nsec, 'nsec', 'i32') }}} // resolution is milliseconds
return 0;
},
@@ -8230,7 +8237,7 @@ LibraryManager.library = {
},
accept__deps: ['$FS', '$SOCKFS', '$DNS', '$ERRNO_CODES', '__setErrNo', '_write_sockaddr'],
- accept: function(fd, addrp, addrlen) {
+ accept: function(fd, addr, addrlen) {
var sock = SOCKFS.getSocket(fd);
if (!sock) {
___setErrNo(ERRNO_CODES.EBADF);
@@ -8238,7 +8245,7 @@ LibraryManager.library = {
}
try {
var newsock = sock.sock_ops.accept(sock);
- if (addrp) {
+ if (addr) {
var res = __write_sockaddr(addr, newsock.family, DNS.lookup_name(newsock.daddr), newsock.dport);
assert(!res.errno);
}
@@ -8669,21 +8676,28 @@ LibraryManager.library = {
},
emscripten_asm_const: function(code) {
- // code is a constant string on the heap, so we can cache these
- if (!Runtime.asmConstCache) Runtime.asmConstCache = {};
- var func = Runtime.asmConstCache[code];
- if (func) return func();
- func = Runtime.asmConstCache[code] = eval('(function(){ ' + Pointer_stringify(code) + ' })'); // new Function does not allow upvars in node
- return func();
+ Runtime.getAsmConst(code, 0)();
+ },
+
+ emscripten_asm_const_int__jsargs: true,
+ emscripten_asm_const_int: function(code) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return Runtime.getAsmConst(code, args.length).apply(null, args) | 0;
+ },
+
+ emscripten_asm_const_double__jsargs: true,
+ emscripten_asm_const_double: function(code) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return +Runtime.getAsmConst(code, args.length).apply(null, args);
},
emscripten_get_now: function() {
if (!_emscripten_get_now.actual) {
if (ENVIRONMENT_IS_NODE) {
- _emscripten_get_now.actual = function _emscripten_get_now_actual() {
- var t = process['hrtime']();
- return t[0] * 1e3 + t[1] / 1e6;
- }
+ _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']) {
@@ -8695,6 +8709,17 @@ LibraryManager.library = {
return _emscripten_get_now.actual();
},
+ emscripten_get_now_res: function() { // return resolution of get_now, in nanoseconds
+ if (ENVIRONMENT_IS_NODE) {
+ return 1; // nanoseconds
+ } else if (typeof dateNow !== 'undefined' ||
+ (ENVIRONMENT_IS_WEB && window['performance'] && window['performance']['now'])) {
+ return 1000; // microseconds (1/1000 of a millisecond)
+ } else {
+ return 1000*1000; // milliseconds
+ }
+ },
+
//============================
// emscripten vector ops
//============================
diff --git a/src/library_browser.js b/src/library_browser.js
index 1883c3be..8444fb73 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -250,7 +250,9 @@ mergeInto(LibraryManager.library, {
contextAttributes.preserveDrawingBuffer = true;
#endif
- ctx = canvas.getContext('experimental-webgl', contextAttributes);
+ ['experimental-webgl', 'webgl'].some(function(webglId) {
+ return ctx = canvas.getContext(webglId, contextAttributes);
+ });
} else {
ctx = canvas.getContext('2d');
}
diff --git a/src/library_sdl.js b/src/library_sdl.js
index f780e15a..eb8eea97 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -2675,7 +2675,7 @@ var LibrarySDL = {
SDL_WaitThread: function() { throw 'SDL_WaitThread' },
SDL_GetThreadID: function() { throw 'SDL_GetThreadID' },
- SDL_ThreadID: function() { throw 'SDL_ThreadID' },
+ SDL_ThreadID: function() { return 0; },
SDL_AllocRW: function() { throw 'SDL_AllocRW: TODO' },
SDL_CondBroadcast: function() { throw 'SDL_CondBroadcast: TODO' },
SDL_CondWaitTimeout: function() { throw 'SDL_CondWaitTimeout: TODO' },
diff --git a/src/preamble.js b/src/preamble.js
index 27016c14..ff9200fc 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -246,7 +246,7 @@ var EXITSTATUS = 0;
var undef = 0;
// tempInt is used for 32-bit signed values or smaller. tempBigInt is used
// for 32-bit unsigned values or more than 32 bits. TODO: audit all uses of tempInt
-var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD;
+var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD, tempDouble, tempFloat;
#if USE_TYPED_ARRAYS == 2
var tempI64, tempI64b;
var tempRet0, tempRet1, tempRet2, tempRet3, tempRet4, tempRet5, tempRet6, tempRet7, tempRet8, tempRet9;
diff --git a/src/runtime.js b/src/runtime.js
index 786ae021..dedaf5ea 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -381,6 +381,18 @@ var Runtime = {
#endif
},
+ getAsmConst: function(code, numArgs) {
+ // code is a constant string on the heap, so we can cache these
+ if (!Runtime.asmConstCache) Runtime.asmConstCache = {};
+ var func = Runtime.asmConstCache[code];
+ if (func) return func;
+ var args = [];
+ for (var i = 0; i < numArgs; i++) {
+ args.push(String.fromCharCode(36) + i); // $0, $1 etc
+ }
+ return Runtime.asmConstCache[code] = eval('(function(' + args.join(',') + '){ ' + Pointer_stringify(code) + ' })'); // new Function does not allow upvars in node
+ },
+
warnOnce: function(text) {
if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {};
if (!Runtime.warnOnce.shown[text]) {
diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h
index ac880981..ddcbc43a 100644
--- a/system/include/emscripten/emscripten.h
+++ b/system/include/emscripten/emscripten.h
@@ -24,17 +24,38 @@ extern "C" {
* EM_ASM(window.alert('hai'));
*
* This also works with asm.js, as it outlines the code (it
- * does a function call to reach it).
+ * does a function call to reach it). It supports newlines,
*
- * Notes: double-quotes (") are not supported, but you can use
+ * EM_ASM(
+ * window.alert('hai'));
+ * window.alert('bai'));
+ * )
+ *
+ * Notes: Double-quotes (") are not supported, but you can use
* single-quotes (') in js anyhow.
*
- * you can't access C variables with EM_ASM, use gcc
- * inline asm for that, asm("code" : .. etc.)
+ * You can't access C variables with EM_ASM, nor receive
+ * a value back. use EM_ASM_INT or EM_ASM_DOUBLE for that
*/
#define EM_ASM(...) emscripten_asm_const(#__VA_ARGS__)
/*
+ * Input-output versions of EM_ASM. EM_ASM_INT receives arguments of
+ * either int or double type and returns an int; EM_ASM_DOUBLE
+ * receives similar arguments (int or double) but returns a double.
+ * Arguments arrive as $0, $1 etc; output value should be returned:
+ *
+ * int x = EM_ASM_INT({
+ * console.log('I received: ' + [$0, $1]);
+ * return $0 + $1;
+ * }, calc(), otherCalc());
+ *
+ * Note the {,}
+ */
+#define EM_ASM_INT(code, ...) emscripten_asm_const_int(#code, __VA_ARGS__)
+#define EM_ASM_DOUBLE(code, ...) emscripten_asm_const_double(#code, __VA_ARGS__)
+
+/*
* Forces LLVM to not dead-code-eliminate a function. Note that
* you still need to use EXPORTED_FUNCTIONS so it stays alive
* in JS, e.g.
@@ -423,6 +444,8 @@ void emscripten_jcache_printf_(...); /* internal use */
/* Helper API for EM_ASM - do not call this yourself */
void emscripten_asm_const(const char *code);
+int emscripten_asm_const_int(const char *code, ...);
+double emscripten_asm_const_double(const char *code, ...);
#ifdef __cplusplus
}
diff --git a/tests/freealut/CMakeLists.txt b/tests/freealut/CMakeLists.txt
index 640f35bf..c11680cd 100644
--- a/tests/freealut/CMakeLists.txt
+++ b/tests/freealut/CMakeLists.txt
@@ -72,20 +72,39 @@ ADD_DEFINE("__NO_CTYPE 1")
ADD_DEFINITIONS(-DHAVE_CONFIG_H)
ADD_DEFINITIONS(-DNDEBUG)
-FIND_LIBRARY(OPENAL_LIB NAMES openal openal32 PATHS /usr/lib /usr/local/lib ${OPENAL_LIB_DIR})
-IF(OPENAL_LIB MATCHES "NOTFOUND")
- MESSAGE(FATAL_ERROR "OpenAL not installed, cannot build alut - aborting.")
-ENDIF(OPENAL_LIB MATCHES "NOTFOUND")
-
-IF(UNIX)
- SET(ADD_LIBS ${ADD_LIBS} m)
-ENDIF(UNIX)
+if (EMSCRIPTEN)
+ # Emscripten cannot use FIND_LIBRARY, since that seaches for linkable library files, but Emscripten supports
+ # OpenAL in core and there are no library files to link against. Instead, use a custom OpenAL package finder
+ # provided by Emscripten.
+ FIND_PACKAGE(OpenAL)
+
+ # All the include file checks bloew are no-ops for Emscripten, so for that platform, just define the flags we support.
+ SET(HAVE_STDINT_H 1)
+ SET(HAVE_STAT 1)
+ SET(HAVE_NANOSLEEP 1)
+ SET(HAVE_TIME_H 1)
+ ADD_DEFINITIONS(-DHAVE_STDINT_H=1 -DHAVE_STAT=1 -DHAVE_NANOSLEEP=1 -DHAVE_TIME_H=1)
+ SET(CMAKE_EXECUTABLE_SUFFIX ".bc")
+else()
+ FIND_LIBRARY(OPENAL_LIB NAMES openal openal32 PATHS /usr/lib /usr/local/lib ${OPENAL_LIB_DIR})
+
+ IF(OPENAL_LIB MATCHES "NOTFOUND")
+ MESSAGE(FATAL_ERROR "OpenAL not installed, cannot build alut - aborting.")
+ ENDIF(OPENAL_LIB MATCHES "NOTFOUND")
+
+ IF(UNIX)
+ SET(ADD_LIBS ${ADD_LIBS} m)
+ ENDIF(UNIX)
+endif()
SET(CMAKE_REQUIRED_INCLUDES ${OPENAL_INCLUDE_DIR})
-CHECK_INCLUDE_FILES("AL/alc.h;AL/al.h" AL_HEADERS)
-IF(NOT AL_HEADERS)
- MESSAGE(FATAL_ERROR "OpenAL header files not found - aborting.")
-ENDIF(NOT AL_HEADERS)
+
+if (NOT EMSCRIPTEN) # Emscripten is a cross-compiler and cannot verify paths of include files with CHECK_INCLUDE_FILES, since that requires building native executables.
+ CHECK_INCLUDE_FILES("AL/alc.h;AL/al.h" AL_HEADERS)
+ IF(NOT AL_HEADERS)
+ MESSAGE(FATAL_ERROR "OpenAL header files not found - aborting.")
+ ENDIF(NOT AL_HEADERS)
+endif()
IF(DEFINED OPENAL_INCLUDE_DIR)
INCLUDE_DIRECTORIES(${OPENAL_INCLUDE_DIR})
@@ -178,10 +197,18 @@ INSTALL_FILES(/lib/pkgconfig FILES admin/pkgconfig/freealut.pc)
IF(BUILD_TESTS)
# examples
ADD_EXECUTABLE(hello_world examples/hello_world.c)
- TARGET_LINK_LIBRARIES(hello_world ${OPENAL_LIB} ${ADD_LIBS} alut)
+ if (EMSCRIPTEN)
+ TARGET_LINK_LIBRARIES(hello_world ${OPENAL_LIB} ${ADD_LIBS} alut_static)
+ else()
+ TARGET_LINK_LIBRARIES(hello_world ${OPENAL_LIB} ${ADD_LIBS} alut)
+ endif()
ADD_EXECUTABLE(playfile examples/playfile.c)
- TARGET_LINK_LIBRARIES(playfile ${OPENAL_LIB} ${ADD_LIBS} alut)
+ if (EMSCRIPTEN)
+ TARGET_LINK_LIBRARIES(playfile ${OPENAL_LIB} ${ADD_LIBS} alut_static)
+ else()
+ TARGET_LINK_LIBRARIES(playfile ${OPENAL_LIB} ${ADD_LIBS} alut)
+ endif()
SET(TESTS errorstuff
diff --git a/tests/runner.py b/tests/runner.py
index 7f513635..34435383 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -16,7 +16,7 @@ so you may prefer to use fewer cores here.
'''
from subprocess import Popen, PIPE, STDOUT
-import os, unittest, tempfile, shutil, time, inspect, sys, math, glob, re, difflib, webbrowser, hashlib, threading, platform, BaseHTTPServer, multiprocessing, functools, stat, string
+import os, unittest, tempfile, shutil, time, inspect, sys, math, glob, re, difflib, webbrowser, hashlib, threading, platform, BaseHTTPServer, SimpleHTTPServer, multiprocessing, functools, stat, string
# Setup
@@ -491,22 +491,14 @@ def harness_server_func(q):
httpd.serve_forever() # test runner will kill us
def server_func(dir, q):
- class TestServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
- def do_GET(s):
- if 'report_' in s.path:
- q.put(s.path)
+ class TestServerHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
+ def do_GET(self):
+ if 'report_' in self.path:
+ q.put(self.path)
else:
- filename = s.path.split('?')[0][1:]
- if os.path.exists(filename):
- s.send_response(200)
- s.send_header("Content-type", "text/html")
- s.end_headers()
- s.wfile.write(open(filename).read())
- s.wfile.close()
- else:
- s.send_response(500)
- s.send_header("Content-type", "text/html")
- s.end_headers()
+ # Use SimpleHTTPServer default file serving operation for GET.
+ SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
+
def log_request(code=0, size=0):
# don't log; too noisy
pass
diff --git a/tests/sockets/test_sockets_echo_server.c b/tests/sockets/test_sockets_echo_server.c
index dbc912a6..55ace660 100644
--- a/tests/sockets/test_sockets_echo_server.c
+++ b/tests/sockets/test_sockets_echo_server.c
@@ -72,7 +72,16 @@ void main_loop(void *arg) {
#if !USE_UDP
// for TCP sockets, we may need to accept a connection
if (FD_ISSET(server.fd, &fdr)) {
+#if TEST_ACCEPT_ADDR
+ // Do an accept with non-NULL addr and addlen parameters. This tests a fix to a bug in the implementation of
+ // accept which had a parameter "addrp" but used "addr" internally if addrp was set - giving a ReferenceError.
+ struct sockaddr_in addr = {0};
+ addr.sin_family = AF_INET;
+ socklen_t addrlen = sizeof(addr);
+ client.fd = accept(server.fd, (struct sockaddr *) &addr, &addrlen);
+#else
client.fd = accept(server.fd, NULL, NULL);
+#endif
assert(client.fd != -1);
}
#endif
diff --git a/tests/test_browser.py b/tests/test_browser.py
index 65bccb38..128820b3 100644
--- a/tests/test_browser.py
+++ b/tests/test_browser.py
@@ -1,12 +1,54 @@
-import BaseHTTPServer, multiprocessing, os, shutil, subprocess, unittest
+import BaseHTTPServer, multiprocessing, os, shutil, subprocess, unittest, zlib, webbrowser, time, shlex
from runner import BrowserCore, path_from_root
from tools.shared import *
-''' Enable this code to run in another browser than webbrowser detects as default
-def run_in_other_browser(url):
- execute(['yourbrowser', url])
-webbrowser.open_new = run_in_other_browser
-'''
+# User can specify an environment variable EMSCRIPTEN_BROWSER to force the browser test suite to
+# run using another browser command line than the default system browser.
+emscripten_browser = os.environ.get('EMSCRIPTEN_BROWSER')
+if emscripten_browser:
+ cmd = shlex.split(emscripten_browser)
+ def run_in_other_browser(url):
+ Popen(cmd + [url])
+ webbrowser.open_new = run_in_other_browser
+
+def test_chunked_synchronous_xhr_server(support_byte_ranges, chunkSize, data, checksum):
+ class ChunkedServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+ def sendheaders(s, extra=[], length=len(data)):
+ s.send_response(200)
+ s.send_header("Content-Length", str(length))
+ s.send_header("Access-Control-Allow-Origin", "http://localhost:8888")
+ s.send_header("Access-Control-Expose-Headers", "Content-Length, Accept-Ranges")
+ s.send_header("Content-type", "application/octet-stream")
+ if support_byte_ranges:
+ s.send_header("Accept-Ranges", "bytes")
+ for i in extra:
+ s.send_header(i[0], i[1])
+ s.end_headers()
+
+ def do_HEAD(s):
+ s.sendheaders()
+
+ def do_OPTIONS(s):
+ s.sendheaders([("Access-Control-Allow-Headers", "Range")], 0)
+
+ def do_GET(s):
+ if not support_byte_ranges:
+ s.sendheaders()
+ s.wfile.write(data)
+ else:
+ (start, end) = s.headers.get("range").split("=")[1].split("-")
+ start = int(start)
+ end = int(end)
+ end = min(len(data)-1, end)
+ length = end-start+1
+ s.sendheaders([],length)
+ s.wfile.write(data[start:end+1])
+ s.wfile.close()
+
+ expectedConns = 11
+ httpd = BaseHTTPServer.HTTPServer(('localhost', 11111), ChunkedServerHandler)
+ for i in range(expectedConns+1):
+ httpd.handle_request()
class browser(BrowserCore):
@staticmethod
@@ -69,7 +111,6 @@ class browser(BrowserCore):
cwd=self.get_dir()).communicate()
assert os.path.exists(html_file)
assert os.path.exists(html_file + '.map')
- import webbrowser, time
webbrowser.open_new('file://' + html_file)
time.sleep(1)
print '''
@@ -85,7 +126,10 @@ If manually bisecting:
cwd = os.getcwd()
try:
os.chdir(path_from_root('third_party', 'lzma.js'))
- Popen(['sh', './doit.sh']).communicate()
+ if WINDOWS and Building.which('mingw32-make'): # On Windows prefer using MinGW make if it exists, otherwise fall back to hoping we have cygwin make.
+ Popen(['doit.bat']).communicate()
+ else:
+ Popen(['sh', './doit.sh']).communicate()
finally:
os.chdir(cwd)
@@ -185,7 +229,7 @@ If manually bisecting:
self.reftest(path_from_root('tests', 'htmltest.png'))
output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_sdl.cpp'), '-o', 'something.js', '-g', '--split', '100', '--pre-js', 'reftest.js']).communicate()
assert os.path.exists(os.path.join(self.get_dir(), 'something.js')), 'must be main js file'
- assert os.path.exists(self.get_dir() + '/something/' + path_from_root('tests', 'hello_world_sdl.cpp.js')), 'must be functions js file'
+ assert os.path.exists(os.path.join(self.get_dir(), 'something', 'hello_world_sdl.cpp.js')), 'must be functions js file'
assert os.path.exists(os.path.join(self.get_dir(), 'something.include.html')), 'must be js include file'
open(os.path.join(self.get_dir(), 'something.html'), 'w').write('''
@@ -1159,8 +1203,14 @@ keydown(100);keyup(100); // trigger the end
Popen([PYTHON, EMCC, '-O2', os.path.join(self.get_dir(), 'test_egl_width_height.c'), '-o', 'page.html']).communicate()
self.run_browser('page.html', 'Should print "(300, 150)" -- the size of the canvas in pixels', '/report_result?1')
+ def get_freealut_library(self):
+ if WINDOWS and Building.which('cmake'):
+ return self.get_library('freealut', os.path.join('hello_world.bc'), configure=['cmake', '.'], configure_args=['-DBUILD_TESTS=ON'])
+ else:
+ return self.get_library('freealut', os.path.join('examples', '.libs', 'hello_world.bc'), make_args=['EXEEXT=.bc'])
+
def test_freealut(self):
- programs = self.get_library('freealut', os.path.join('examples', '.libs', 'hello_world.bc'), make_args=['EXEEXT=.bc'])
+ programs = self.get_freealut_library()
for program in programs:
assert os.path.exists(program)
Popen([PYTHON, EMCC, '-O2', program, '-o', 'page.html']).communicate()
@@ -1256,51 +1306,16 @@ keydown(100);keyup(100); // trigger the end
chunkSize = 1024
data = os.urandom(10*chunkSize+1) # 10 full chunks and one 1 byte chunk
- expectedConns = 11
- import zlib
checksum = zlib.adler32(data)
- def chunked_server(support_byte_ranges):
- class ChunkedServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
- def sendheaders(s, extra=[], length=len(data)):
- s.send_response(200)
- s.send_header("Content-Length", str(length))
- s.send_header("Access-Control-Allow-Origin", "http://localhost:8888")
- s.send_header("Access-Control-Expose-Headers", "Content-Length, Accept-Ranges")
- s.send_header("Content-type", "application/octet-stream")
- if support_byte_ranges:
- s.send_header("Accept-Ranges", "bytes")
- for i in extra:
- s.send_header(i[0], i[1])
- s.end_headers()
-
- def do_HEAD(s):
- s.sendheaders()
-
- def do_OPTIONS(s):
- s.sendheaders([("Access-Control-Allow-Headers", "Range")], 0)
-
- def do_GET(s):
- if not support_byte_ranges:
- s.sendheaders()
- s.wfile.write(data)
- else:
- (start, end) = s.headers.get("range").split("=")[1].split("-")
- start = int(start)
- end = int(end)
- end = min(len(data)-1, end)
- length = end-start+1
- s.sendheaders([],length)
- s.wfile.write(data[start:end+1])
- s.wfile.close()
- httpd = BaseHTTPServer.HTTPServer(('localhost', 11111), ChunkedServerHandler)
- for i in range(expectedConns+1):
- httpd.handle_request()
-
- server = multiprocessing.Process(target=chunked_server, args=(True,))
+ server = multiprocessing.Process(target=test_chunked_synchronous_xhr_server, args=(True,chunkSize,data,checksum,))
server.start()
self.run_browser(main, 'Chunked binary synchronous XHR in Web Workers!', '/report_result?' + str(checksum))
server.terminate()
+ # Avoid race condition on cleanup, wait a bit so that processes have released file locks so that test tearDown won't
+ # attempt to rmdir() files in use.
+ if WINDOWS:
+ time.sleep(2)
def test_glgears(self):
self.btest('hello_world_gles.c', reference='gears.png', reference_slack=1,
diff --git a/tests/test_core.py b/tests/test_core.py
index d7b6cf53..67e316e4 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -3970,7 +3970,7 @@ def process(filename):
#include <stdio.h>
#include <emscripten.h>
- int main() {
+ int main(int argc, char **argv) {
EM_ASM(Module.print('hello dere1'));
EM_ASM(
Module.print('hello dere2');
@@ -3981,11 +3981,19 @@ def process(filename):
Module.print('hello dere' + 4);
);
}
+ int sum = 0;
+ for (int i = 0; i < argc*3; i++) {
+ sum += EM_ASM_INT({
+ Module.print('i: ' + [$0, ($1).toFixed(2)]);
+ return $0*2;
+ }, i, double(i)/12);
+ }
+ printf("sum: %d\n", sum);
return 0;
}
'''
- self.do_run(src, 'hello dere1\nhello dere2\nhello dere3\nhello dere4\nhello dere3\nhello dere4\nhello dere3\nhello dere4\n')
+ self.do_run(src, 'hello dere1\nhello dere2\nhello dere3\nhello dere4\nhello dere3\nhello dere4\nhello dere3\nhello dere4\ni: 0,0.00\ni: 1,0.08\ni: 2,0.17\nsum: 6\n')
def test_memorygrowth(self):
if Settings.USE_TYPED_ARRAYS == 0: return self.skip('memory growth is only supported with typed arrays')
diff --git a/tests/test_sanity.py b/tests/test_sanity.py
index a405c3a3..c7dd86e4 100644
--- a/