From cad88b317c1ffbbc397b86ca4b65cb837c9c9ea7 Mon Sep 17 00:00:00 2001
From: Alon Zakai <alonzakai@gmail.com>
Date: Tue, 27 May 2014 11:36:57 -0700
Subject: [PATCH 01/12] proper error message for linkable modules not supported
 in fastcomp

---
 emcc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/emcc b/emcc
index ae9423cd944e9..342af478564d4 100755
--- a/emcc
+++ b/emcc
@@ -1272,6 +1272,7 @@ try:
       assert shared.Settings.INIT_HEAP == 0, 'HEAP_INIT is not supported in fastcomp (and should never be needed except for debugging)'
       assert not shared.Settings.RUNTIME_TYPE_INFO, 'RUNTIME_TYPE_INFO is not supported in fastcomp'
       assert not shared.Settings.CORRUPTION_CHECK, 'CORRUPTION_CHECK is not supported in asm.js mode, which is what fastcomp can emit (you can use non-asm.js mode in non-fastcomp)'
+      assert not shared.Settings.MAIN_MODULE and not shared.Settings.SIDE_MODULE, 'Linking modules is not supported in fastcomp'
     except Exception, e:
       logging.error('Compiler settings are incompatible with fastcomp. You can fall back to the older compiler core, although that is not recommended, see https://github.com/kripken/emscripten/wiki/LLVM-Backend')
       raise e

From a9798715cf9414f4656b349c7f7f9ad2db1b2bd2 Mon Sep 17 00:00:00 2001
From: Alon Zakai <alonzakai@gmail.com>
Date: Tue, 27 May 2014 13:50:45 -0700
Subject: [PATCH 02/12] testcase for #2314

---
 tests/cases/floatundefinvoke_fastcomp.ll  | 30 +++++++++++++++++++++++
 tests/cases/floatundefinvoke_fastcomp.txt |  3 +++
 2 files changed, 33 insertions(+)
 create mode 100644 tests/cases/floatundefinvoke_fastcomp.ll
 create mode 100644 tests/cases/floatundefinvoke_fastcomp.txt

diff --git a/tests/cases/floatundefinvoke_fastcomp.ll b/tests/cases/floatundefinvoke_fastcomp.ll
new file mode 100644
index 0000000000000..215506ef0f980
--- /dev/null
+++ b/tests/cases/floatundefinvoke_fastcomp.ll
@@ -0,0 +1,30 @@
+; ModuleID = 'a.o'
+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:128-n32-S128"
+target triple = "asmjs-unknown-emscripten"
+
+@.str = private unnamed_addr constant [11 x i8] c"float: %f\0A\00", align 1
+
+define void @_Z10printFloatf(float %f) #0 {
+entry:
+  %conv = fpext float %f to double
+  %call = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x i8]* @.str, i32 0, i32 0), double %conv)
+  ret void
+}
+
+define i32 @main() #1 {
+entry:
+  tail call void @_Z10printFloatf(float 1.000000e+00)
+  call void @emscripten_preinvoke()
+  call void @_Z10printFloatf(float undef)
+  %last = call i32 @emscripten_postinvoke()
+  %lastf = sitofp i32 %last to float
+  tail call void @_Z10printFloatf(float %lastf)
+  ret i32 1
+}
+
+declare void @emscripten_preinvoke()
+declare i32 @emscripten_postinvoke()
+declare i32 @printf(i8* nocapture, ...) #1
+
+attributes #0 = { noinline nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
diff --git a/tests/cases/floatundefinvoke_fastcomp.txt b/tests/cases/floatundefinvoke_fastcomp.txt
new file mode 100644
index 0000000000000..5e19391eeffe8
--- /dev/null
+++ b/tests/cases/floatundefinvoke_fastcomp.txt
@@ -0,0 +1,3 @@
+float: 1.000000
+float: 0.000000
+float: 0.000000

From deaf15da8488537086332cc5c64c4bf0bbf49460 Mon Sep 17 00:00:00 2001
From: Alon Zakai <alonzakai@gmail.com>
Date: Tue, 27 May 2014 14:58:31 -0700
Subject: [PATCH 03/12] clean up shell code using uglify, in optimized builds,
 when not using closure

---
 emcc                  |  7 +++++--
 tests/test_other.py   |  6 +++++-
 tools/js_optimizer.py | 28 +++++++++++++++++++---------
 3 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/emcc b/emcc
index 342af478564d4..be9879804ce8d 100755
--- a/emcc
+++ b/emcc
@@ -1794,8 +1794,11 @@ try:
         if emit_symbol_map: js_optimizer_queue += ['symbolMap='+target+'.symbols']
       if debug_level == 0: js_optimizer_queue += ['minifyWhitespace']
 
-    if closure and shared.Settings.ASM_JS:
-      js_optimizer_queue += ['closure']
+    if shared.Settings.ASM_JS:
+      if closure:
+        js_optimizer_queue += ['closure']
+      elif debug_level <= 2 and not shared.Settings.MAIN_MODULE and not shared.Settings.SIDE_MODULE:
+        js_optimizer_queue += ['cleanup']
 
     if not shared.Settings.SIDE_MODULE: js_optimizer_queue += ['last'] # side modules are not finalized until after relocation
 
diff --git a/tests/test_other.py b/tests/test_other.py
index 12dd7872ec5e0..03859a4e75e9f 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -203,6 +203,10 @@ def test_emcc(self):
         (['--typed-arrays', '1'], lambda generated: 'IHEAPU = ' in generated, 'typed arrays 1 selected'),
         (['--typed-arrays', '2'], lambda generated: 'new Uint16Array' in generated and 'new Uint32Array' in generated, 'typed arrays 2 selected'),
         (['--llvm-opts', '1'], lambda generated: '_puts(' in generated, 'llvm opts requested'),
+        ([], lambda generated: '// The Module object' in generated, 'without opts, comments in shell code'),
+        (['-O2'], lambda generated: '// The Module object' not in generated, 'with opts, no comments in shell code'),
+        (['-O2', '-g2'], lambda generated: '// The Module object' not in generated, 'with -g2, no comments in shell code'),
+        (['-O2', '-g3'], lambda generated: '// The Module object' in generated, 'with -g3, yes comments in shell code'),
       ]:
         print params, text
         self.clear()
@@ -2218,7 +2222,7 @@ def test_module_exports_with_closure(self):
     test_js_closure_0 = open(path_from_root('tests', 'Module-exports', 'test.js')).read()
 
     # Check that test.js compiled with --closure 0 contains "module['exports'] = Module;"
-    assert "module['exports'] = Module;" in test_js_closure_0
+    assert ("module['exports'] = Module;" in test_js_closure_0) or ('module["exports"]=Module' in test_js_closure_0)
 
     # Check that main.js (which requires test.js) completes successfully when run in node.js
     # in order to check that the exports are indeed functioning correctly.
diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py
index d02845281efa2..e06c2d2f57fe3 100644
--- a/tools/js_optimizer.py
+++ b/tools/js_optimizer.py
@@ -137,6 +137,10 @@ def run_on_js(filename, passes, js_engine, jcache, source_map=False, extra_info=
   if closure:
     passes = filter(lambda p: p != 'closure', passes) # we will do it manually
 
+  cleanup = 'cleanup' in passes
+  if cleanup:
+    passes = filter(lambda p: p != 'cleanup', passes) # we will do it manually
+
   if not know_generated and jcache:
     # JCache cannot be used without metadata, since it might reorder stuff, and that's dangerous since only generated can be reordered
     # This means jcache does not work after closure compiler runs, for example. But you won't get much benefit from jcache with closure
@@ -291,23 +295,29 @@ def write_chunk(chunk, i):
 
   for filename in filenames: temp_files.note(filename)
 
-  if closure:
-    # run closure on the shell code, everything but what we js-optimize
+  if closure or cleanup:
+    # run on the shell code, everything but what we js-optimize
     start_asm = '// EMSCRIPTEN_START_ASM\n'
     end_asm = '// EMSCRIPTEN_END_ASM\n'
-    closure_sep = 'wakaUnknownBefore(); var asm=wakaUnknownAfter(global,env,buffer)\n'
+    cl_sep = 'wakaUnknownBefore(); var asm=wakaUnknownAfter(global,env,buffer)\n'
 
-    closuree = temp_files.get('.closure.js').name
-    c = open(closuree, 'w')
+    cle = temp_files.get('.cl.js').name
+    c = open(cle, 'w')
     pre_1, pre_2 = pre.split(start_asm)
     post_1, post_2 = post.split(end_asm)
     c.write(pre_1)
-    c.write(closure_sep)
+    c.write(cl_sep)
     c.write(post_2)
     c.close()
-    closured = shared.Building.closure_compiler(closuree, pretty='minifyWhitespace' not in passes)
-    temp_files.note(closured)
-    coutput = open(closured).read()
+    if closure:
+      if DEBUG: print >> sys.stderr, 'running closure on shell code'
+      cld = shared.Building.closure_compiler(cle, pretty='minifyWhitespace' not in passes)
+    else:
+      if DEBUG: print >> sys.stderr, 'running cleanup on shell code'
+      cld = cle + '.js'
+      subprocess.Popen(js_engine + [JS_OPTIMIZER, cle, 'noPrintMetadata'] + (['minifyWhitespace'] if 'minifyWhitespace' in passes else []), stdout=open(cld, 'w')).communicate()
+    temp_files.note(cld)
+    coutput = open(cld).read()
     coutput = coutput.replace('wakaUnknownBefore();', '')
     after = 'wakaUnknownAfter'
     start = coutput.find(after)

From afd5a42acfb5885bcb48aae1a5114396f5e54481 Mon Sep 17 00:00:00 2001
From: Alon Zakai <alonzakai@gmail.com>
Date: Tue, 27 May 2014 16:22:37 -0700
Subject: [PATCH 04/12] fix crash in audio code in bananabread

---
 src/library_sdl.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/library_sdl.js b/src/library_sdl.js
index fd8c686063156..a01b3c6ca1163 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -2332,7 +2332,7 @@ var LibrarySDL = {
       return 0;
     }
 
-    var arrayBuffer = bytes.buffer || bytes;
+    var arrayBuffer = bytes ? bytes.buffer || bytes : bytes;
 
     // To allow user code to work around browser bugs with audio playback on <audio> elements an Web Audio, enable
     // the user code to hook in a callback to decide on a file basis whether each file should use Web Audio or <audio> for decoding and playback.

From e792dc4e6aea8bd4b95eada40f85e8c0598dfc3d Mon Sep 17 00:00:00 2001
From: Alon Zakai <alonzakai@gmail.com>
Date: Tue, 27 May 2014 17:20:12 -0700
Subject: [PATCH 05/12] fix ccall regex for minified code, and add testing

---
 src/preamble.js    | 2 +-
 tests/test_core.py | 8 +++++---
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/preamble.js b/src/preamble.js
index fbce6b6b65b1d..58b442abffd5a 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -396,7 +396,7 @@ var cwrap, ccall;
     return ret;
   }
 
-  var sourceRegex = /^function\s\((.*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/;
+  var sourceRegex = /^function\s\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/;
   function parseJSFunc(jsfunc) {
     // Match the body and the return value of a javascript function source
     var parsed = jsfunc.toString().match(sourceRegex).slice(1);
diff --git a/tests/test_core.py b/tests/test_core.py
index 46d3964c6d05f..7e15f1b8a6d0a 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -5453,9 +5453,6 @@ def test_corruption_3(self):
   ### Integration tests
 
   def test_ccall(self):
-    if self.emcc_args is not None and '-O2' in self.emcc_args:
-      self.emcc_args += ['--closure', '1'] # Use closure here, to test we export things right
-
     post = '''
 def process(filename):
   src = \'\'\'
@@ -5499,6 +5496,11 @@ def process(filename):
 
     self.do_run_from_file(src, output, post_build=post)
 
+    if self.emcc_args is not None and '-O2' in self.emcc_args:
+      print 'with closure'
+      self.emcc_args += ['--closure', '1']
+      self.do_run_from_file(src, output, post_build=post)
+
   def test_pgo(self):
     if Settings.ASM_JS: return self.skip('PGO does not work in asm mode')
 

From a2aef0f9212b0bc147aeb850c398b52ae98eaa3e Mon Sep 17 00:00:00 2001
From: Alon Zakai <alonzakai@gmail.com>
Date: Wed, 28 May 2014 10:05:08 -0700
Subject: [PATCH 06/12] fix asm2.test_memorygrowth

---
 tests/test_core.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/test_core.py b/tests/test_core.py
index 7e15f1b8a6d0a..1d04ebcb32650 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -2068,10 +2068,10 @@ def test_memorygrowth(self):
 
     if self.emcc_args and '-O2' in self.emcc_args:
       # Make sure ALLOW_MEMORY_GROWTH generates different code (should be less optimized)
-      code_start = 'var TOTAL_MEMORY = '
+      code_start = 'var TOTAL_MEMORY'
       fail = fail[fail.find(code_start):]
       win = win[win.find(code_start):]
-      assert len(fail) < len(win), 'failing code - without memory growth on - is more optimized, and smaller'
+      assert len(fail) < len(win), 'failing code - without memory growth on - is more optimized, and smaller' + str([len(fail), len(win)])
 
   def test_ssr(self): # struct self-ref
       src = '''

From 079a9b3e1f317d8e96602a44be4569d670905930 Mon Sep 17 00:00:00 2001
From: Alon Zakai <alonzakai@gmail.com>
Date: Wed, 28 May 2014 10:09:07 -0700
Subject: [PATCH 07/12] fix slow2asm.test_dlfcn_self

---
 tests/test_core.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/test_core.py b/tests/test_core.py
index 1d04ebcb32650..281a3a0bead7b 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -3244,7 +3244,7 @@ def post(filename):
             break
         else:
           raise Exception('Could not find symbol table!')
-      table = table[table.find('{'):table.rfind('}')+1]
+      table = table[table.find('{'):table.find('}')+1]
       # ensure there aren't too many globals; we don't want unnamed_addr
       assert table.count(',') <= 4
 

From a0bb46803b6d84f8105dbc254599be8cb6b9f98d Mon Sep 17 00:00:00 2001
From: Alon Zakai <alonzakai@gmail.com>
Date: Wed, 28 May 2014 13:16:58 -0700
Subject: [PATCH 08/12] fix case of exceptions whitelist being empty

---
 emcc                                          |  4 +--
 .../core/test_exceptions_white_list_empty.out |  0
 tests/test_core.py                            | 27 +++++++++++++++++++
 3 files changed, 29 insertions(+), 2 deletions(-)
 create mode 100644 tests/core/test_exceptions_white_list_empty.out

diff --git a/emcc b/emcc
index be9879804ce8d..e55990dfbcabb 100755
--- a/emcc
+++ b/emcc
@@ -1289,8 +1289,8 @@ try:
     fastcomp_opts += ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt']
     if shared.Settings.DISABLE_EXCEPTION_CATCHING != 1:
       fastcomp_opts += ['-enable-emscripten-cxx-exceptions']
-      if len(shared.Settings.EXCEPTION_CATCHING_WHITELIST) > 0:
-        fastcomp_opts += ['-emscripten-cxx-exceptions-whitelist=' + ','.join(shared.Settings.EXCEPTION_CATCHING_WHITELIST)]
+      if shared.Settings.DISABLE_EXCEPTION_CATCHING == 2:
+        fastcomp_opts += ['-emscripten-cxx-exceptions-whitelist=' + ','.join(shared.Settings.EXCEPTION_CATCHING_WHITELIST or ['fake'])]
 
   if shared.Settings.ASM_JS:
     assert opt_level >= 1 or fastcomp, 'asm.js requires -O1 or above'
diff --git a/tests/core/test_exceptions_white_list_empty.out b/tests/core/test_exceptions_white_list_empty.out
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/tests/test_core.py b/tests/test_core.py
index 281a3a0bead7b..62a061e27eeff 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -1347,6 +1347,33 @@ def test_exceptions_white_list(self):
     test_path = path_from_root('tests', 'core', 'test_exceptions_white_list')
     src, output = (test_path + s for s in ('.in', '.out'))
     self.do_run_from_file(src, output)
+    size = len(open('src.cpp.o.js').read())
+    shutil.copyfile('src.cpp.o.js', 'orig.js')
+
+    if os.environ.get('EMCC_FAST_COMPILER') != '0':
+      # check that an empty whitelist works properly (as in, same as exceptions disabled)
+      empty_output = path_from_root('tests', 'core', 'test_exceptions_white_list_empty.out')
+
+      Settings.EXCEPTION_CATCHING_WHITELIST = []
+      self.do_run_from_file(src, empty_output)
+      empty_size = len(open('src.cpp.o.js').read())
+      shutil.copyfile('src.cpp.o.js', 'empty.js')
+
+      Settings.EXCEPTION_CATCHING_WHITELIST = ['fake']
+      self.do_run_from_file(src, empty_output)
+      fake_size = len(open('src.cpp.o.js').read())
+      shutil.copyfile('src.cpp.o.js', 'fake.js')
+
+      Settings.DISABLE_EXCEPTION_CATCHING = 1
+      self.do_run_from_file(src, empty_output)
+      disabled_size = len(open('src.cpp.o.js').read())
+      shutil.copyfile('src.cpp.o.js', 'disabled.js')
+
+      assert size - empty_size > 2000, [empty_size, size] # big change when we disable entirely
+      assert size - fake_size > 2000, [fake_size, size]
+      assert empty_size == fake_size, [empty_size, fake_size]
+      assert empty_size - disabled_size < 100, [empty_size, disabled_size] # full disable removes a tiny bit more
+      assert fake_size - disabled_size < 100, [disabled_size, fake_size]
 
   def test_exceptions_white_list_2(self):
     Settings.DISABLE_EXCEPTION_CATCHING = 2

From 2bafe8167cf4af7318b0b7183bad993d4ae45fd0 Mon Sep 17 00:00:00 2001
From: Jason Green <jason@transgaming.com>
Date: Tue, 27 May 2014 15:51:54 -0500
Subject: [PATCH 09/12] glTex[Sub]Image* should not throw an exception, but
 should cause a GL_INVALID_ENUM error on unrecognized formats or types

---
 AUTHORS               |   1 +
 src/library_gl.js     |  47 ++++++++++++++---
 tests/gl_teximage.c   | 120 ++++++++++++++++++++++++++++++++++++++++++
 tests/test_browser.py |   3 ++
 4 files changed, 165 insertions(+), 6 deletions(-)
 create mode 100644 tests/gl_teximage.c

diff --git a/AUTHORS b/AUTHORS
index 7994f80e26ba4..65354d07e7891 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -138,3 +138,4 @@ a license to everyone to use it as detailed in LICENSE.)
 * Guillaume Blanc <guillaumeblanc.sc@gmail.com>
 * Usagi Ito <usagi@WonderRabbitProject.net>
 * Camilo Polymeris <cpolymeris@gmail.com>
+* Jason Green <jason@transgaming.com> (copyright owned by TransGaming, Inc.)
diff --git a/src/library_gl.js b/src/library_gl.js
index 851b01b182880..2659a9d985f10 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -431,21 +431,42 @@ var LibraryGL = {
               sizePerPixel = 2;
               break;
             default:
-              throw 'Invalid format (' + format + ')';
+              GL.recordError(0x0500); // GL_INVALID_ENUM
+#if GL_ASSERTIONS
+              Module.printErr('GL_INVALID_ENUM in glTex[Sub]Image, type: ' + type + ', format: ' + format);
+#endif
+              return {
+                pixels: null,
+                internalFormat: 0x0
+              };
           }
           break;
         case 0x1403 /* GL_UNSIGNED_SHORT */:
           if (format == 0x1902 /* GL_DEPTH_COMPONENT */) {
             sizePerPixel = 2;
           } else {
-            throw 'Invalid format (' + format + ')';
+            GL.recordError(0x0500); // GL_INVALID_ENUM
+#if GL_ASSERTIONS
+            Module.printErr('GL_INVALID_ENUM in glTex[Sub]Image, type: ' + type + ', format: ' + format);
+#endif
+            return {
+              pixels: null,
+              internalFormat: 0x0
+            };
           }
           break;
         case 0x1405 /* GL_UNSIGNED_INT */:
           if (format == 0x1902 /* GL_DEPTH_COMPONENT */) {
             sizePerPixel = 4;
           } else {
-            throw 'Invalid format (' + format + ')';
+            GL.recordError(0x0500); // GL_INVALID_ENUM
+#if GL_ASSERTIONS
+            Module.printErr('GL_INVALID_ENUM in glTex[Sub]Image, type: ' + type + ', format: ' + format);
+#endif
+            return {
+              pixels: null,
+              internalFormat: 0x0
+            };
           }
           break;
         case 0x84FA /* UNSIGNED_INT_24_8_WEBGL */:
@@ -468,12 +489,26 @@ var LibraryGL = {
               sizePerPixel = 4*4;
               break;
             default:
-              throw 'Invalid format (' + format + ')';
+              GL.recordError(0x0500); // GL_INVALID_ENUM
+#if GL_ASSERTIONS
+              Module.printErr('GL_INVALID_ENUM in glTex[Sub]Image, type: ' + type + ', format: ' + format);
+#endif
+              return {
+                pixels: null,
+                internalFormat: 0x0
+              };
           }
           internalFormat = GLctx.RGBA;
           break;
         default:
-          throw 'Invalid type (' + type + ')';
+          GL.recordError(0x0500); // GL_INVALID_ENUM
+#if GL_ASSERTIONS
+          Module.printErr('GL_INVALID_ENUM in glTex[Sub]Image, type: ' + type + ', format: ' + format);
+#endif
+          return {
+            pixels: null,
+            internalFormat: 0x0
+          };
       }
       var bytes = GL.computeImageSize(width, height, sizePerPixel, GL.unpackAlignment);
       if (type == 0x1401 /* GL_UNSIGNED_BYTE */) {
@@ -488,7 +523,7 @@ var LibraryGL = {
       return {
         pixels: pixels,
         internalFormat: internalFormat
-      }
+      };
     },
 
 #if GL_FFP_ONLY
diff --git a/tests/gl_teximage.c b/tests/gl_teximage.c
new file mode 100644
index 0000000000000..9cafce9c7076e
--- /dev/null
+++ b/tests/gl_teximage.c
@@ -0,0 +1,120 @@
+/*
+ * GLES2 test for glTexImage2D parameters
+ *
+ * Original author: Jason Green <jason@transgaming.com>
+ *
+ */
+#include "GLES2/gl2.h"
+#include "SDL/SDL.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <emscripten.h>
+#include <unistd.h>
+
+typedef enum {
+    TEST_STATUS_SUCCESS = 0,
+    TEST_STATUS_FAILURE = 1
+} TestStatus;
+
+/* Report success or failure (1 or 0) to Emscripten's test harness. Also, exit
+ * with the given error code. */
+static void exit_with_status(TestStatus code)
+{
+#ifdef REPORT_RESULT
+    int result = (code == TEST_STATUS_SUCCESS) ? 1 : 0;
+    REPORT_RESULT();
+#endif
+
+    exit(code);
+}
+
+/* Loop over all glGetError() results until GL reports GL_NO_ERROR */
+static void clear_gl_errors()
+{
+    GLenum err;
+    do {
+        err = glGetError();
+    } while (err != GL_NO_ERROR);
+}
+
+int main(int argc, char *argv[])
+{
+    TestStatus passed = TEST_STATUS_SUCCESS;
+    SDL_Surface *screen;
+
+    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
+        printf("SDL_Init failed with %s\n", SDL_GetError());
+        exit_with_status(TEST_STATUS_FAILURE);
+    }
+
+    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+    screen = SDL_SetVideoMode(640, 480, 16, SDL_OPENGL);
+    if (!screen) {
+        printf("SDL_SetVideoMode failed with %s\n", SDL_GetError());
+        exit_with_status(TEST_STATUS_FAILURE);
+    }
+
+    GLuint texture;
+    glGenTextures(1, &texture);
+
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+    // Allocate space for a 32x32 image with 4 bytes per pixel.
+    // No need to fill it with any useful information, as these tests are
+    // only designed to make sure glTexImage2D doesn't crash on unsupported
+    // formats.
+    void* pixels = malloc(4 * 32 * 32);
+    if (pixels == NULL) {
+        printf("Unable to allocate pixel data\n");
+        exit_with_status(TEST_STATUS_FAILURE);
+    }
+
+    // First, try 0xffff for the internal format - should fail
+    glTexImage2D(GL_TEXTURE_2D, 0, 0xffff, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+    GLenum err = glGetError();
+    if (err == GL_NO_ERROR) {
+        printf("internal format == 0xffff succeeded, but should have failed\n");
+        passed = TEST_STATUS_FAILURE;
+    }
+    clear_gl_errors();
+
+    // Try 0xffff for the format - should fail
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, 0xffff, GL_UNSIGNED_BYTE, pixels);
+    err = glGetError();
+    if (err == GL_NO_ERROR) {
+        printf("format == 0xffff succeeded, but should have failed\n");
+        passed = TEST_STATUS_FAILURE;
+    }
+    clear_gl_errors();
+
+    // Try 0xffff for the type - should fail
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, 0xffff, pixels);
+    err = glGetError();
+    if (err == GL_NO_ERROR) {
+        printf("type == 0xffff succeeded, but should have failed\n");
+        passed = TEST_STATUS_FAILURE;
+    }
+    clear_gl_errors();
+
+    // Try GL_RGBA/GL_UNSIGNED_BYTE - should succeed
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+    err = glGetError();
+    if (err != GL_NO_ERROR) {
+        printf("GL_RGBA/GL_UNSIGNED_BYTE failed with %x, but should have succeeded\n", err);
+        passed = TEST_STATUS_FAILURE;
+    }
+    clear_gl_errors();
+
+    // Clean up objects
+    glBindTexture(GL_TEXTURE_2D, 0);
+    glDeleteTextures(1, &texture);
+    free(pixels);
+
+    // 'screen' is freed implicitly by SDL_Quit()
+    SDL_Quit();
+
+    exit_with_status(passed);
+}
diff --git a/tests/test_browser.py b/tests/test_browser.py
index aedc926a66631..c8e07b252a96a 100644
--- a/tests/test_browser.py
+++ b/tests/test_browser.py
@@ -1425,6 +1425,9 @@ def test_glgetattachedshaders(self):
   def test_sdlglshader(self):
     self.btest('sdlglshader.c', reference='sdlglshader.png', args=['-O2', '--closure', '1', '-s', 'LEGACY_GL_EMULATION=1'])
 
+  def test_gl_glteximage(self):
+    self.btest('gl_teximage.c', '1')
+
   def test_gl_ps(self):
     # pointers and a shader
     shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))

From 504b62384aba8da8258ed6f8ba0a455a1db7736a Mon Sep 17 00:00:00 2001
From: Alon Zakai <alonzakai@gmail.com>
Date: Wed, 28 May 2014 14:50:35 -0700
Subject: [PATCH 10/12] add emscripten_align typedefs for #2378

---
 system/include/emscripten/emscripten.h | 26 ++++++++++++++
 tests/core/test_set_align.c            | 50 ++++++++++++++++++++++++++
 tests/core/test_set_align.out          |  8 +++++
 tests/test_core.py                     |  9 +++++
 4 files changed, 93 insertions(+)
 create mode 100644 tests/core/test_set_align.c
 create mode 100644 tests/core/test_set_align.out

diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h
index 66017a8ddf5b0..8a08aabb87695 100644
--- a/system/include/emscripten/emscripten.h
+++ b/system/include/emscripten/emscripten.h
@@ -18,6 +18,32 @@ extern "C" {
 #include <SDL/SDL.h> /* for SDL_Delay in async_call */
 #endif
 
+
+/* Typedefs */
+
+/*
+ * Unaligned types, helpful to force LLVM to emit unaligned
+ * loads/stores in places in your code where SAFE_HEAP found
+ * an unaligned operation. (It's better to avoid unaligned
+ * operations, but if you are reading from a packed stream of
+ * bytes or such, these types may be useful.)
+ */
+
+typedef short __attribute__((aligned(1))) emscripten_align1_short;
+
+typedef int __attribute__((aligned(2))) emscripten_align2_int;
+typedef int __attribute__((aligned(1))) emscripten_align1_int;
+
+typedef float __attribute__((aligned(2))) emscripten_align2_float;
+typedef float __attribute__((aligned(1))) emscripten_align1_float;
+
+typedef double __attribute__((aligned(4))) emscripten_align4_double;
+typedef double __attribute__((aligned(2))) emscripten_align2_double;
+typedef double __attribute__((aligned(1))) emscripten_align1_double;
+
+
+/* Functions */
+
 /*
  * Convenient syntax for inline assembly/js. Allows stuff like
  *
diff --git a/tests/core/test_set_align.c b/tests/core/test_set_align.c
new file mode 100644
index 0000000000000..26158ef428eba
--- /dev/null
+++ b/tests/core/test_set_align.c
@@ -0,0 +1,50 @@
+
+#include <stdio.h>
+#include <emscripten.h>
+ 
+volatile char data[16];
+ 
+__attribute__((noinline)) void *get_aligned(int align)
+{
+  char *ptr = (char*)(((int)(data + 7)) & ~7); // Make 8-byte aligned
+  ptr += align; // Now 'align' aligned
+  return (void*)ptr;
+}
+ 
+int main()
+{
+  emscripten_align4_double *d4 = (emscripten_align4_double*)get_aligned(4);
+  *d4 = 17.0;
+  printf("addr: %d, value: %f\n", ((int)d4) % 8, *d4);
+
+  emscripten_align2_double *d2 = (emscripten_align2_double*)get_aligned(2);
+  *d2 = 18.0;
+  printf("addr: %d, value: %f\n", ((int)d2) % 8, *d2);
+
+  emscripten_align1_double *d1 = (emscripten_align1_double*)get_aligned(1);
+  *d1 = 19.0;
+  printf("addr: %d, value: %f\n", ((int)d1) % 8, *d1);
+
+  emscripten_align2_float *f2 = (emscripten_align2_float*)get_aligned(2);
+  *f2 = 20.0;
+  printf("addr: %d, value: %f\n", ((int)f2) % 4, *f2);
+
+  emscripten_align1_float *f1 = (emscripten_align1_float*)get_aligned(1);
+  *f1 = 21.0;
+  printf("addr: %d, value: %f\n", ((int)f1) % 4, *f1);
+
+  emscripten_align2_int *i2 = (emscripten_align2_int*)get_aligned(2);
+  *i2 = 22;
+  printf("addr: %d, value: %d\n", ((int)i2) % 4, *i2);
+
+  emscripten_align1_int *i1 = (emscripten_align1_int*)get_aligned(1);
+  *i1 = 23;
+  printf("addr: %d, value: %d\n", ((int)i1) % 4, *i1);
+
+  emscripten_align1_short *s1 = (emscripten_align1_short*)get_aligned(1);
+  *s1 = 24;
+  printf("addr: %d, value: %d\n", ((int)s1) % 4, (int)*s1);
+
+  return 0;
+}
+
diff --git a/tests/core/test_set_align.out b/tests/core/test_set_align.out
new file mode 100644
index 0000000000000..55e377b028ab2
--- /dev/null
+++ b/tests/core/test_set_align.out
@@ -0,0 +1,8 @@
+addr: 4, value: 17.000000
+addr: 2, value: 18.000000
+addr: 1, value: 19.000000
+addr: 2, value: 20.000000
+addr: 1, value: 21.000000
+addr: 2, value: 22
+addr: 1, value: 23
+addr: 1, value: 24
diff --git a/tests/test_core.py b/tests/test_core.py
index 62a061e27eeff..505a051bdb310 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -1980,6 +1980,15 @@ def test_llvm_used(self):
 
     self.do_run_from_file(src, output)
 
+  def test_set_align(self):
+    if self.run_name == 'slow2asm': return self.skip('FIXME in slow2asm')
+
+    Settings.SAFE_HEAP = 1
+
+    test_path = path_from_root('tests', 'core', 'test_set_align')
+    src, output = (test_path + s for s in ('.c', '.out'))
+    self.do_run_from_file(src, output)
+
   def test_emscripten_api(self):
       #if Settings.MICRO_OPTS or Settings.RELOOP or Building.LLVM_OPTS: return self.skip('FIXME')
 

From 34599322eea3c9d2240c1c09d0f148f95612ed5a Mon Sep 17 00:00:00 2001
From: Chad Austin <chad@imvu.com>
Date: Wed, 28 May 2014 11:20:50 -0700
Subject: [PATCH 11/12] Fix a bug where a returned handle to a derived JS
 object would not always correctly increment the reference count of the
 underlying smart pointer.

---
 src/embind/embind.js        | 15 ++++++++++++---
 tests/embind/embind.test.js |  1 +
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/src/embind/embind.js b/src/embind/embind.js
index 124ea5698ef16..8c8d73ad52e52 100644
--- a/src/embind/embind.js
+++ b/src/embind/embind.js
@@ -1216,9 +1216,18 @@ RegisteredPointer.prototype['fromWireType'] = function fromWireType(ptr) {
 
     var registeredInstance = getInheritedInstance(this.registeredClass, rawPointer);
     if (undefined !== registeredInstance) {
-        var rv = registeredInstance['clone']();
-        this.destructor(ptr);
-        return rv;
+        // JS object has been neutered, time to repopulate it
+        if (0 === registeredInstance.$$.count.value) {
+            registeredInstance.$$.ptr = rawPointer;
+            registeredInstance.$$.smartPtr = ptr;
+            return registeredInstance['clone']();
+        } else {
+            // else, just increment reference count on existing object
+            // it already has a reference to the smart pointer
+            var rv = registeredInstance['clone']();
+            this.destructor(ptr);
+            return rv;
+        }
     }
 
     function makeDefaultHandle() {
diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js
index a6b2e98ccae5f..432202ff3c28e 100644
--- a/tests/embind/embind.test.js
+++ b/tests/embind/embind.test.js
@@ -2410,6 +2410,7 @@ module({
             var back = holder.get();
             assert.equal(back, instance);
             holder.delete();
+            back.delete();
         });
     });
 

From 4ae305542c80f31b06c5e8325c63ade2bb4a3f33 Mon Sep 17 00:00:00 2001
From: Alon Zakai <alonzakai@gmail.com>
Date: Thu, 29 May 2014 13:44:16 -0700
Subject: [PATCH 12/12] 1.19.0

---
 emscripten-version.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/emscripten-version.txt b/emscripten-version.txt
index ca3ca78e64f82..c6dc663de916f 100644
--- a/emscripten-version.txt
+++ b/emscripten-version.txt
@@ -1,2 +1,2 @@
-1.18.4
+1.19.0