diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs
index fc81c1bf..b6eae8c1 100644
--- a/crates/backend/src/codegen.rs
+++ b/crates/backend/src/codegen.rs
@@ -974,28 +974,12 @@ impl TryToTokens for ast::ImportFunction {
         }
 
         let mut exceptional_ret = quote!();
-        let exn_data = if self.catch {
-            let exn_data = Ident::new("exn_data", Span::call_site());
-            let exn_data_ptr = Ident::new("exn_data_ptr", Span::call_site());
-            abi_argument_names.push(exn_data_ptr.clone());
-            abi_arguments.push(quote! { #exn_data_ptr: *mut u32 });
+        if self.catch {
             convert_ret = quote! { Ok(#convert_ret) };
             exceptional_ret = quote! {
-                if #exn_data[0] == 1 {
-                    return Err(
-                        <
-                            wasm_bindgen::JsValue as wasm_bindgen::convert::FromWasmAbi
-                        >::from_abi(#exn_data[1], &mut wasm_bindgen::convert::GlobalStack::new())
-                    )
-                }
+                wasm_bindgen::__rt::take_last_exception()?;
             };
-            quote! {
-                let mut #exn_data = [0; 2];
-                let #exn_data_ptr = #exn_data.as_mut_ptr();
-            }
-        } else {
-            quote!()
-        };
+        }
 
         let rust_name = &self.rust_name;
         let import_name = &self.shim;
@@ -1055,7 +1039,6 @@ impl TryToTokens for ast::ImportFunction {
                 #extern_fn
 
                 unsafe {
-                    #exn_data
                     let #ret_ident = {
                         let mut __stack = wasm_bindgen::convert::GlobalStack::new();
                         #(#arg_conversions)*
diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs
index dad09461..94793302 100644
--- a/crates/cli-support/src/js/mod.rs
+++ b/crates/cli-support/src/js/mod.rs
@@ -1419,16 +1419,14 @@ impl<'a> Context<'a> {
         if !self.should_write_global("handle_error") {
             return Ok(());
         }
-        self.expose_uint32_memory();
+        self.require_internal_export("__wbindgen_exn_store")?;
         if self.config.anyref {
             self.expose_add_to_anyref_table()?;
             self.global(
                 "
-                function handleError(exnptr, e) {
+                function handleError(e) {
                     const idx = addToAnyrefTable(e);
-                    const view = getUint32Memory();
-                    view[exnptr / 4] = 1;
-                    view[exnptr / 4 + 1] = idx;
+                    wasm.__wbindgen_exn_store(idx);
                 }
                 ",
             );
@@ -1436,10 +1434,8 @@ impl<'a> Context<'a> {
             self.expose_add_heap_object();
             self.global(
                 "
-                function handleError(exnptr, e) {
-                    const view = getUint32Memory();
-                    view[exnptr / 4] = 1;
-                    view[exnptr / 4 + 1] = addHeapObject(e);
+                function handleError(e) {
+                    wasm.__wbindgen_exn_store(addHeapObject(e));
                 }
                 ",
             );
@@ -2115,7 +2111,7 @@ impl<'a> Context<'a> {
 
     fn export_function_table(&mut self) -> Result<(), Error> {
         if !self.should_write_global("wbg-function-table") {
-            return Ok(())
+            return Ok(());
         }
         let id = match self.module.tables.main_function_table()? {
             Some(id) => id,
@@ -2192,7 +2188,7 @@ impl ExportedClass {
         field: &str,
         js: &str,
         prefix: &str,
-        ret_ty: &str
+        ret_ty: &str,
     ) -> &mut bool {
         self.contents.push_str(docs);
         self.contents.push_str(prefix);
@@ -2215,7 +2211,8 @@ impl ExportedClass {
 /// generated output is deterministic and we do so by ensuring that iteration of
 /// hash maps is consistently sorted.
 fn sorted_iter<K, V>(map: &HashMap<K, V>) -> impl Iterator<Item = (&K, &V)>
-    where K: Ord,
+where
+    K: Ord,
 {
     let mut pairs = map.iter().collect::<Vec<_>>();
     pairs.sort_by_key(|(k, _)| *k);
diff --git a/crates/cli-support/src/js/rust2js.rs b/crates/cli-support/src/js/rust2js.rs
index b2d39ada..097f3413 100644
--- a/crates/cli-support/src/js/rust2js.rs
+++ b/crates/cli-support/src/js/rust2js.rs
@@ -928,7 +928,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
                 try {{\n\
                     {}
                 }} catch (e) {{\n\
-                    handleError(exnptr, e);\n\
+                    handleError(e);\n\
                 }}\
                 ",
                 &invoc
@@ -973,12 +973,6 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
         let mut ret = String::new();
         ret.push_str("function(");
         ret.push_str(&self.shim_arguments.join(", "));
-        if self.catch {
-            if self.shim_arguments.len() > 0 {
-                ret.push_str(", ")
-            }
-            ret.push_str("exnptr");
-        }
         ret.push_str(") {\n");
         ret.push_str(&self.prelude);
 
diff --git a/src/lib.rs b/src/lib.rs
index f6097f99..0d8ffe5b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1067,6 +1067,28 @@ pub mod __rt {
     pub fn link_mem_intrinsics() {
         crate::anyref::link_intrinsics();
     }
+
+    static mut GLOBAL_EXNDATA: [u32; 2] = [0; 2];
+
+    #[no_mangle]
+    pub unsafe extern "C" fn __wbindgen_exn_store(idx: u32) {
+        assert_eq!(GLOBAL_EXNDATA[0], 0);
+        GLOBAL_EXNDATA[0] = 1;
+        GLOBAL_EXNDATA[1] = idx;
+    }
+
+    pub fn take_last_exception() -> Result<(), super::JsValue> {
+        unsafe {
+            let ret = if GLOBAL_EXNDATA[0] == 1 {
+                Err(super::JsValue:: _new(GLOBAL_EXNDATA[1]))
+            } else {
+                Ok(())
+            };
+            GLOBAL_EXNDATA[0] = 0;
+            GLOBAL_EXNDATA[1] = 0;
+            return ret;
+        }
+    }
 }
 
 /// A wrapper type around slices and vectors for binding the `Uint8ClampedArray`