Handle fatal runtime errors (#1151)

* Handle fatal runtime errors

* Wrote "fatal_error" code

* Fix _pyproxy_set

* Fix ownkeys

* Fix PyProxy.toString
This commit is contained in:
Hood Chatham 2021-01-20 14:18:19 -08:00 committed by GitHub
parent 829e2d4d1e
commit a8c38fe289
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 96 additions and 25 deletions

View File

@ -69,10 +69,9 @@ _pyproxy_set(PyObject* pyobj, JsRef idkey, JsRef idval)
Py_DECREF(pyval);
if (result) {
pythonexc2js();
return NULL;
}
return idval;
return hiwire_incref(idval);
}
JsRef
@ -89,7 +88,6 @@ _pyproxy_deleteProperty(PyObject* pyobj, JsRef idkey)
Py_DECREF(pykey);
if (ret) {
pythonexc2js();
return NULL;
}
@ -102,7 +100,6 @@ _pyproxy_ownKeys(PyObject* pyobj)
PyObject* pydir = PyObject_Dir(pyobj);
if (pydir == NULL) {
pythonexc2js();
return NULL;
}
@ -133,7 +130,6 @@ _pyproxy_apply(PyObject* pyobj, JsRef idargs)
PyObject* pyresult = PyObject_Call(pyobj, pyargs, NULL);
if (pyresult == NULL) {
Py_DECREF(pyargs);
pythonexc2js();
return NULL;
}
JsRef idresult = python2js(pyresult);
@ -191,7 +187,15 @@ EM_JS(int, pyproxy_init, (), {
Module.PyProxyPublicMethods = {
toString : function() {
let ptrobj = _getPtr(this);
let jsref_repr = __pyproxy_repr(ptrobj);
let jsref_repr;
try {
jsref_repr = __pyproxy_repr(ptrobj);
} catch(e){
Module.fatal_error(e);
}
if(jsref_repr === 0){
_pythonexc2js();
}
let repr = Module.hiwire.get_value(jsref_repr);
Module.hiwire.decref(jsref_repr);
return repr;
@ -204,10 +208,19 @@ EM_JS(int, pyproxy_init, (), {
apply : function(jsthis, jsargs) {
let ptrobj = _getPtr(this);
let idargs = Module.hiwire.new_value(jsargs);
let idresult = __pyproxy_apply(ptrobj, idargs);
let idresult;
try {
idresult = __pyproxy_apply(ptrobj, idargs);
} catch(e){
Module.fatal_error(e);
} finally {
Module.hiwire.decref(idargs);
}
if(idresult === 0){
_pythonexc2js();
}
let jsresult = Module.hiwire.get_value(idresult);
Module.hiwire.decref(idresult);
Module.hiwire.decref(idargs);
return jsresult;
},
};
@ -224,9 +237,18 @@ EM_JS(int, pyproxy_init, (), {
}
let ptrobj = _getPtr(jsobj);
let idkey = Module.hiwire.new_value(jskey);
let result = __pyproxy_has(ptrobj, idkey) !== 0;
Module.hiwire.decref(idkey);
return result;
let result;
try {
result = __pyproxy_has(ptrobj, idkey);
} catch(e){
Module.fatal_error(e);
} finally {
Module.hiwire.decref(idkey);
}
if(result === -1){
_pythonexc2js();
}
return result !== 0;
},
get: function (jsobj, jskey) {
if(Reflect.has(jsobj, jskey) && !ignoredTargetFields.includes(jskey)){
@ -234,9 +256,18 @@ EM_JS(int, pyproxy_init, (), {
}
let ptrobj = _getPtr(jsobj);
let idkey = Module.hiwire.new_value(jskey);
let idresult = __pyproxy_get(ptrobj, idkey);
let idresult;
try {
idresult = __pyproxy_get(ptrobj, idkey);
} catch(e) {
Module.fatal_error(e);
} finally {
Module.hiwire.decref(idkey);
}
if(idresult === 0){
_pythonexc2js();
}
let jsresult = Module.hiwire.get_value(idresult);
Module.hiwire.decref(idkey);
Module.hiwire.decref(idresult);
return jsresult;
},
@ -247,10 +278,19 @@ EM_JS(int, pyproxy_init, (), {
let ptrobj = _getPtr(jsobj);
let idkey = Module.hiwire.new_value(jskey);
let idval = Module.hiwire.new_value(jsval);
let idresult = __pyproxy_set(ptrobj, idkey, idval);
let idresult;
try {
idresult = __pyproxy_set(ptrobj, idkey, idval);
} catch(e) {
Module.fatal_error(e);
} finally {
Module.hiwire.decref(idkey);
Module.hiwire.decref(idval);
}
if(idresult === 0){
_pythonexc2js();
}
let jsresult = Module.hiwire.get_value(idresult);
Module.hiwire.decref(idkey);
Module.hiwire.decref(idval);
Module.hiwire.decref(idresult);
return jsresult;
},
@ -260,10 +300,19 @@ EM_JS(int, pyproxy_init, (), {
}
let ptrobj = _getPtr(jsobj);
let idkey = Module.hiwire.new_value(jskey);
let idresult = __pyproxy_deleteProperty(ptrobj, idkey);
let idresult;
try {
idresult = __pyproxy_deleteProperty(ptrobj, idkey);
} catch(e) {
Module.fatal_error(e);
} finally {
Module.hiwire.decref(idkey);
}
if(idresult === 0){
_pythonexc2js();
}
let jsresult = Module.hiwire.get_value(idresult);
Module.hiwire.decref(idresult);
Module.hiwire.decref(idkey);
return jsresult;
},
ownKeys: function (jsobj) {
@ -272,7 +321,12 @@ EM_JS(int, pyproxy_init, (), {
result.delete(key);
}
let ptrobj = _getPtr(jsobj);
let idresult = __pyproxy_ownKeys(ptrobj);
let idresult;
try {
idresult = __pyproxy_ownKeys(ptrobj);
} catch(e) {
Module.fatal_error(e);
}
let jsresult = Module.hiwire.get_value(idresult);
Module.hiwire.decref(idresult);
for(let key of jsresult){

View File

@ -358,11 +358,6 @@ python2js_with_depth(PyObject* x, int depth)
PyObject* map = PyDict_New();
JsRef result = _python2js_cache(x, map, depth);
Py_DECREF(map);
if (result == NULL) {
pythonexc2js();
}
return result;
}

View File

@ -319,6 +319,7 @@ globalThis.languagePluginLoader = new Promise((resolve, reject) => {
function makePublicAPI(module, public_api) {
let namespace = {_module : module};
module.public_api = namespace;
for (let name of public_api) {
namespace[name] = module[name];
}
@ -336,6 +337,27 @@ globalThis.languagePluginLoader = new Promise((resolve, reject) => {
Module.preloadedWasm = {};
let isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
Module.fatal_error = function(e) {
for (let [key, value] of Object.entries(Module.public_api)) {
if (key.startsWith("_")) {
// delete Module.public_api[key];
continue;
}
// Have to do this case first because typeof(some_pyproxy) === "function".
if (Module.PyProxy.isPyProxy(value)) {
value.destroy();
continue;
}
if (typeof (value) === "function") {
Module.public_api[key] = function() {
throw Error("Pyodide has suffered a fatal error, refresh the page. " +
"Please report this to the Pyodide maintainers.");
}
}
}
throw e;
};
Module.runPython = code => Module.pyodide_py.eval_code(code, Module.globals);
// clang-format off

View File

@ -30,7 +30,7 @@ def test_threading_import(selenium):
selenium.run(
"""
import threading
threading.local()
threading.local(); pass
"""
)