Thankfully this was a lot easier than tracing hiwire keys. 

I located one actual leak: if an error is thrown during `to_js` it would forget to free `proxies`. Other than that, I fixed a few "dumb leaks" in `api.js` where we leak the methods like `eval_code` or `find_imports`. So the code was already in surprisingly good shape in this way.

It's still possible that we leak some Python objects somehow, but this is as good as we can do for systematic checks short of compiling Python itself with `TRACE_MALLOC`.
Eliminate pyproxy leaks. Thankfully this was a lot easier than tracing hiwire keys. 

I located one actual leak: if an error is thrown during `to_js` it would forget to free `proxies`. Other than that, I fixed a few "dumb leaks" in `api.js` where we leak the methods like `eval_code` or `find_imports`. So the code was already in surprisingly good shape in this way.

It's still possible that we leak some Python objects somehow, but this is as good as we can do for systematic checks short of compiling Python itself with `TRACE_MALLOC`.
Make return values to fortran subroutines be consistently int.

This is because f2py defaults to making subroutines return void, whereas
f2c makes them int. On most systems this doesn't matter, but on WASM, strict
return type checking is used which makes things fail when f2py code calls
subroutines that were generated from fortran with f2c. To fix this we make
everything, including f2c, return int from subroutines.

diff --git a/numpy/f2py/common_rules.py b/numpy/f2py/common_rules.py
index 62c1ba207..54a445d37 100644
--- a/numpy/f2py/common_rules.py
+++ b/numpy/f2py/common_rules.py
@@ -117,7 +117,7 @@ def buildhooks(m):
             F_FUNC = 'F_FUNC_US'
         else:
             F_FUNC = 'F_FUNC'
-        cadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void(*)(%s));'
+        cadd('extern int %s(f2pyinit%s,F2PYINIT%s)(void(*)(%s));'
              % (F_FUNC, lower_name, name.upper(),
                 ','.join(['char*'] * len(inames1))))
         cadd('static void f2py_init_%s(void) {' % name)
diff --git a/numpy/f2py/rules.py b/numpy/f2py/rules.py
index 1b41498ea..9419aeb16 100755
--- a/numpy/f2py/rules.py
+++ b/numpy/f2py/rules.py
@@ -399,9 +399,9 @@ rout_rules = [
         'decl': '',
         '_check': ismoduleroutine
     }, {  # Subroutine
-        'functype': 'void',
-        'declfortranroutine': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'extern void #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
-                               l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)): 'extern void #fortranname#(#callprotoargument#);',
+        'functype': 'int',
+        'declfortranroutine': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'extern int #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
+                               l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)): 'extern int #fortranname#(#callprotoargument#);',
                                ismoduleroutine: '',
                                isdummyroutine: ''
                                },
diff --git a/numpy/f2py/src/fortranobject.c b/numpy/f2py/src/fortranobject.c
index b55385b50..232a7f90d 100644
--- a/numpy/f2py/src/fortranobject.c
+++ b/numpy/f2py/src/fortranobject.c
@@ -308,6 +308,11 @@ fortran_getattr(PyFortranObject *fp, char *name) {
         return s;
     }
     if ((strcmp(name,"_cpointer")==0) && (fp->len==1)) {
+        if(fp->defs[0].data==NULL)
+        {
+            PyErr_Format(PyExc_AttributeError,"missing function pointer %s",fp->defs[0].name);
+
+        }
         PyObject *cobj = F2PyCapsule_FromVoidPtr((void *)(fp->defs[0].data),NULL);
         if (PyDict_SetItemString(fp->dict, name, cobj))
             return NULL;
@@ -382,7 +387,7 @@ fortran_setattr(PyFortranObject *fp, char *name, PyObject *v) {
     if (v == NULL) {
         int rv = PyDict_DelItemString(fp->dict, name);
         if (rv < 0)
-            PyErr_SetString(PyExc_AttributeError,"delete non-existing fortran attribute");
+            PyErr_Format(PyExc_AttributeError,"delete non-existing fortran attribute %s",name);
         return rv;
     }
     else
diff --git a/numpy/linalg/lapack_lite/f2c.c b/numpy/linalg/lapack_lite/f2c.c
index 1114bef3b..905beaa0d 100644
--- a/numpy/linalg/lapack_lite/f2c.c
+++ b/numpy/linalg/lapack_lite/f2c.c
@@ -14,9 +14,9 @@
 #include "f2c.h"
 
 
-extern void s_wsfe(cilist *f) {;}
-extern void e_wsfe(void) {;}
-extern void do_fio(integer *c, char *s, ftnlen l) {;}
+extern int s_wsfe(cilist *f) {return 0;}
+extern int e_wsfe(void) {return 0;}
+extern int do_fio(integer *c, char *s, ftnlen l) {return 0;}
 
 /* You'll want this if you redo the f2c_*.c files with the -C option
  * to f2c for checking array subscripts. (It's not suggested you do that
@@ -377,7 +377,7 @@ p->i = p1.i;
 
 #endif /* NO_OVERWRITE */
 
- VOID
+ int
 #ifdef KR_headers
 s_cat(lp, rpp, rnp, np, ll) char *lp, *rpp[]; ftnlen rnp[], *np, ll;
 #else
@@ -487,7 +487,7 @@ return(0);
 #ifdef KR_headers
 VOID s_copy(a, b, la, lb) register char *a, *b; ftnlen la, lb;
 #else
-void s_copy(register char *a, register char *b, ftnlen la, ftnlen lb)
+int s_copy(register char *a, register char *b, ftnlen la, ftnlen lb)
 #endif
 {
 	register char *aend, *bend;
@@ -524,6 +524,7 @@ void s_copy(register char *a, register char *b, ftnlen la, ftnlen lb)
 		while(a < aend)
 			*a++ = ' ';
 		}
+        return 0;
 	}
 
 
diff --git a/numpy/linalg/lapack_lite/f2c.h b/numpy/linalg/lapack_lite/f2c.h
index 80f1a12b1..25204797b 100644
--- a/numpy/linalg/lapack_lite/f2c.h
+++ b/numpy/linalg/lapack_lite/f2c.h
@@ -259,7 +259,7 @@ extern double d_tan(double *);
 extern double d_tanh(double *);
 extern double derf_(double *);
 extern double derfc_(double *);
-extern void do_fio(ftnint *, char *, ftnlen);
+extern int do_fio(ftnint *, char *, ftnlen);
 extern integer do_lio(ftnint *, ftnint *, char *, ftnlen);
 extern integer do_uio(ftnint *, char *, ftnlen);
 extern integer e_rdfe(void);
@@ -271,7 +271,7 @@ extern integer e_rsli(void);
 extern integer e_rsue(void);
 extern integer e_wdfe(void);
 extern integer e_wdue(void);
-extern void e_wsfe(void);
+extern int e_wsfe(void);
 extern integer e_wsfi(void);
 extern integer e_wsle(void);
 extern integer e_wsli(void);
@@ -346,9 +346,9 @@ extern double r_sinh(float *);
 extern double r_sqrt(float *);
 extern double r_tan(float *);
 extern double r_tanh(float *);
-extern void s_cat(char *, char **, integer *, integer *, ftnlen);
+extern int s_cat(char *, char **, integer *, integer *, ftnlen);
 extern integer s_cmp(char *, char *, ftnlen, ftnlen);
-extern void s_copy(char *, char *, ftnlen, ftnlen);
+extern int s_copy(char *, char *, ftnlen, ftnlen);
 extern int s_paus(char *, ftnlen);
 extern integer s_rdfe(cilist *);
 extern integer s_rdue(cilist *);
@@ -363,7 +363,7 @@ extern integer s_rsue(cilist *);
 extern int s_stop(char *, ftnlen);
 extern integer s_wdfe(cilist *);
 extern integer s_wdue(cilist *);
-extern void s_wsfe(	cilist *);
+extern int s_wsfe(	cilist *);
 extern integer s_wsfi(icilist *);
 extern integer s_wsle(cilist *);
 extern integer s_wsli(icilist *);

Make return values to fortran subroutines be consistently int.

This is because f2py defaults to making subroutines return void, whereas
f2c makes them int. On most systems this doesn't matter, but on WASM, strict
return type checking is used which makes things fail when f2py code calls
subroutines that were generated from fortran with f2c. To fix this we make
everything, including f2c, return int from subroutines.

diff --git a/numpy/f2py/common_rules.py b/numpy/f2py/common_rules.py
index 62c1ba207..54a445d37 100644
--- a/numpy/f2py/common_rules.py
+++ b/numpy/f2py/common_rules.py
@@ -117,7 +117,7 @@ def buildhooks(m):
             F_FUNC = 'F_FUNC_US'
         else:
             F_FUNC = 'F_FUNC'
-        cadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void(*)(%s));'
+        cadd('extern int %s(f2pyinit%s,F2PYINIT%s)(void(*)(%s));'
              % (F_FUNC, lower_name, name.upper(),
                 ','.join(['char*'] * len(inames1))))
         cadd('static void f2py_init_%s(void) {' % name)
diff --git a/numpy/f2py/rules.py b/numpy/f2py/rules.py
index 1b41498ea..9419aeb16 100755
--- a/numpy/f2py/rules.py
+++ b/numpy/f2py/rules.py
@@ -399,9 +399,9 @@ rout_rules = [
         'decl': '',
         '_check': ismoduleroutine
     }, {  # Subroutine
-        'functype': 'void',
-        'declfortranroutine': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'extern void #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
-                               l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)): 'extern void #fortranname#(#callprotoargument#);',
+        'functype': 'int',
+        'declfortranroutine': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'extern int #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
+                               l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)): 'extern int #fortranname#(#callprotoargument#);',
                                ismoduleroutine: '',
                                isdummyroutine: ''
                                },
diff --git a/numpy/f2py/src/fortranobject.c b/numpy/f2py/src/fortranobject.c
index b55385b50..232a7f90d 100644
--- a/numpy/f2py/src/fortranobject.c
+++ b/numpy/f2py/src/fortranobject.c
@@ -308,6 +308,11 @@ fortran_getattr(PyFortranObject *fp, char *name) {
         return s;
     }
     if ((strcmp(name,"_cpointer")==0) && (fp->len==1)) {
+        if(fp->defs[0].data==NULL)
+        {
+            PyErr_Format(PyExc_AttributeError,"missing function pointer %s",fp->defs[0].name);
+
+        }
         PyObject *cobj = F2PyCapsule_FromVoidPtr((void *)(fp->defs[0].data),NULL);
         if (PyDict_SetItemString(fp->dict, name, cobj))
             return NULL;
@@ -382,7 +387,7 @@ fortran_setattr(PyFortranObject *fp, char *name, PyObject *v) {
     if (v == NULL) {
         int rv = PyDict_DelItemString(fp->dict, name);
         if (rv < 0)
-            PyErr_SetString(PyExc_AttributeError,"delete non-existing fortran attribute");
+            PyErr_Format(PyExc_AttributeError,"delete non-existing fortran attribute %s",name);
         return rv;
     }
     else
diff --git a/numpy/linalg/lapack_lite/f2c.c b/numpy/linalg/lapack_lite/f2c.c
index 1114bef3b..905beaa0d 100644
--- a/numpy/linalg/lapack_lite/f2c.c
+++ b/numpy/linalg/lapack_lite/f2c.c
@@ -14,9 +14,9 @@
 #include "f2c.h"
 
 
-extern void s_wsfe(cilist *f) {;}
-extern void e_wsfe(void) {;}
-extern void do_fio(integer *c, char *s, ftnlen l) {;}
+extern int s_wsfe(cilist *f) {return 0;}
+extern int e_wsfe(void) {return 0;}
+extern int do_fio(integer *c, char *s, ftnlen l) {return 0;}
 
 /* You'll want this if you redo the f2c_*.c files with the -C option
  * to f2c for checking array subscripts. (It's not suggested you do that
@@ -377,7 +377,7 @@ p->i = p1.i;
 
 #endif /* NO_OVERWRITE */
 
- VOID
+ int
 #ifdef KR_headers
 s_cat(lp, rpp, rnp, np, ll) char *lp, *rpp[]; ftnlen rnp[], *np, ll;
 #else
@@ -487,7 +487,7 @@ return(0);
 #ifdef KR_headers
 VOID s_copy(a, b, la, lb) register char *a, *b; ftnlen la, lb;
 #else
-void s_copy(register char *a, register char *b, ftnlen la, ftnlen lb)
+int s_copy(register char *a, register char *b, ftnlen la, ftnlen lb)
 #endif
 {
 	register char *aend, *bend;
@@ -524,6 +524,7 @@ void s_copy(register char *a, register char *b, ftnlen la, ftnlen lb)
 		while(a < aend)
 			*a++ = ' ';
 		}
+        return 0;
 	}
 
 
diff --git a/numpy/linalg/lapack_lite/f2c.h b/numpy/linalg/lapack_lite/f2c.h
index 80f1a12b1..25204797b 100644
--- a/numpy/linalg/lapack_lite/f2c.h
+++ b/numpy/linalg/lapack_lite/f2c.h
@@ -259,7 +259,7 @@ extern double d_tan(double *);
 extern double d_tanh(double *);
 extern double derf_(double *);
 extern double derfc_(double *);
-extern void do_fio(ftnint *, char *, ftnlen);
+extern int do_fio(ftnint *, char *, ftnlen);
 extern integer do_lio(ftnint *, ftnint *, char *, ftnlen);
 extern integer do_uio(ftnint *, char *, ftnlen);
 extern integer e_rdfe(void);
@@ -271,7 +271,7 @@ extern integer e_rsli(void);
 extern integer e_rsue(void);
 extern integer e_wdfe(void);
 extern integer e_wdue(void);
-extern void e_wsfe(void);
+extern int e_wsfe(void);
 extern integer e_wsfi(void);
 extern integer e_wsle(void);
 extern integer e_wsli(void);
@@ -346,9 +346,9 @@ extern double r_sinh(float *);
 extern double r_sqrt(float *);
 extern double r_tan(float *);
 extern double r_tanh(float *);
-extern void s_cat(char *, char **, integer *, integer *, ftnlen);
+extern int s_cat(char *, char **, integer *, integer *, ftnlen);
 extern integer s_cmp(char *, char *, ftnlen, ftnlen);
-extern void s_copy(char *, char *, ftnlen, ftnlen);
+extern int s_copy(char *, char *, ftnlen, ftnlen);
 extern int s_paus(char *, ftnlen);
 extern integer s_rdfe(cilist *);
 extern integer s_rdue(cilist *);
@@ -363,7 +363,7 @@ extern integer s_rsue(cilist *);
 extern int s_stop(char *, ftnlen);
 extern integer s_wdfe(cilist *);
 extern integer s_wdue(cilist *);
-extern void s_wsfe(	cilist *);
+extern int s_wsfe(	cilist *);
 extern integer s_wsfi(icilist *);
 extern integer s_wsle(cilist *);
 extern integer s_wsli(icilist *);
