diff --git a/Makefile b/Makefile index aa5168c81..9c79b120f 100644 --- a/Makefile +++ b/Makefile @@ -56,6 +56,7 @@ all: check \ build/pyodide.asm.js: src/core/main.o src/core/jsimport.o \ src/core/jsproxy.o src/core/js2python.o \ + src/core/error_handling.o \ src/core/pyproxy.o \ src/core/python2js.o \ src/core/python2js_buffer.o \ diff --git a/src/core/error_handling.c b/src/core/error_handling.c new file mode 100644 index 000000000..4fc307298 --- /dev/null +++ b/src/core/error_handling.c @@ -0,0 +1,25 @@ +#include "error_handling.h" +#include "Python.h" +#include "hiwire.h" +#include "jsproxy.h" +#include + +void +PyodideErr_SetJsError(JsRef err) +{ + PyObject* py_err = JsProxy_new_error(err); + PyErr_SetObject((PyObject*)(py_err->ob_type), py_err); +} + +int +error_handling_init() +{ + EM_ASM({ + Module.handle_js_error = function(e){ + let err = Module.hiwire.new_value(e); + PyodideErr_SetJsError(err); + Module.hiwire.decref(err); +} +}); +return 0; +} diff --git a/src/core/error_handling.h b/src/core/error_handling.h new file mode 100644 index 000000000..14e415183 --- /dev/null +++ b/src/core/error_handling.h @@ -0,0 +1,55 @@ +#ifndef ERROR_HANDLING_H +#define ERROR_HANDLING_H + +/** Wrap EM_JS so that it produces functions that follow the Python return + * conventions. We catch javascript errors and proxy them and use + * `PyErr_SetObject` to hand them off to python. We need two variants, one + * for functions that return pointers / references (return 0) + * the other for functions that return numbers (return -1). + */ + +typedef int errcode; + +// Hiwire wants to import us for errcode, so import hiwire after typedef. +#include "hiwire.h" +#include + +int +error_handling_init(); + +// WARNING: These wrappers around EM_JS cause macros in body to be expanded. +// This causes trouble with true and false. +// In types.h we provide nonstandard definitions: +// false ==> (!!0) +// true ==> (!!1) +// These work as expected in both C and javascript. + +// clang-format off +#define EM_JS_REF(ret, func_name, args, body...) \ + EM_JS(ret, func_name, args, { \ + /* "use strict"; TODO: enable this. */ \ + try /* intentionally no braces, body already has them */ \ + body /* <== body of func */ \ + catch (e) { \ + /* Dummied out until calling code is ready to catch these errors */ \ + throw e; \ + Module.handle_js_error(e); \ + return 0; \ + } \ + }) + +#define EM_JS_NUM(ret, func_name, args, body...) \ + EM_JS(ret, func_name, args, { \ + /* "use strict"; TODO: enable this. */ \ + try /* intentionally no braces, body already has them */ \ + body /* <== body of func */ \ + catch (e) { \ + /* Dummied out until calling code is ready to catch these errors */ \ + throw e; \ + Module.handle_js_error(e); \ + return -1; \ + } \ + }) +// clang-format on + +#endif // ERROR_HANDLING_H diff --git a/src/core/hiwire.c b/src/core/hiwire.c index 8aebb1f9f..6451da2c7 100644 --- a/src/core/hiwire.c +++ b/src/core/hiwire.c @@ -1,3 +1,4 @@ +#include "error_handling.h" #include #include "hiwire.h" @@ -102,7 +103,7 @@ EM_JS(int, hiwire_init, (), { return 0; }); -EM_JS(JsRef, hiwire_incref, (JsRef idval), { +EM_JS_REF(JsRef, hiwire_incref, (JsRef idval), { // clang-format off if ((idval & 1) === 0) { // least significant bit unset ==> idval is a singleton. @@ -113,15 +114,19 @@ EM_JS(JsRef, hiwire_incref, (JsRef idval), { return Module.hiwire.new_value(Module.hiwire.get_value(idval)); }); -EM_JS(void, hiwire_decref, (JsRef idval), { Module.hiwire.decref(idval); }); +EM_JS_NUM(errcode, hiwire_decref, (JsRef idval), { + Module.hiwire.decref(idval); +}); -EM_JS(JsRef, hiwire_int, (int val), { return Module.hiwire.new_value(val); }); - -EM_JS(JsRef, hiwire_double, (double val), { +EM_JS_REF(JsRef, hiwire_int, (int val), { return Module.hiwire.new_value(val); }); -EM_JS(JsRef, hiwire_string_ucs4, (const char* ptr, int len), { +EM_JS_REF(JsRef, hiwire_double, (double val), { + return Module.hiwire.new_value(val); +}); + +EM_JS_REF(JsRef, hiwire_string_ucs4, (const char* ptr, int len), { var jsstr = ""; var idx = ptr / 4; for (var i = 0; i < len; ++i) { @@ -130,7 +135,7 @@ EM_JS(JsRef, hiwire_string_ucs4, (const char* ptr, int len), { return Module.hiwire.new_value(jsstr); }); -EM_JS(JsRef, hiwire_string_ucs2, (const char* ptr, int len), { +EM_JS_REF(JsRef, hiwire_string_ucs2, (const char* ptr, int len), { var jsstr = ""; var idx = ptr / 2; for (var i = 0; i < len; ++i) { @@ -139,7 +144,7 @@ EM_JS(JsRef, hiwire_string_ucs2, (const char* ptr, int len), { return Module.hiwire.new_value(jsstr); }); -EM_JS(JsRef, hiwire_string_ucs1, (const char* ptr, int len), { +EM_JS_REF(JsRef, hiwire_string_ucs1, (const char* ptr, int len), { var jsstr = ""; var idx = ptr; for (var i = 0; i < len; ++i) { @@ -148,81 +153,84 @@ EM_JS(JsRef, hiwire_string_ucs1, (const char* ptr, int len), { return Module.hiwire.new_value(jsstr); }); -EM_JS(JsRef, hiwire_string_utf8, (const char* ptr), { +EM_JS_REF(JsRef, hiwire_string_utf8, (const char* ptr), { return Module.hiwire.new_value(UTF8ToString(ptr)); }); -EM_JS(JsRef, hiwire_string_ascii, (const char* ptr), { +EM_JS_REF(JsRef, hiwire_string_ascii, (const char* ptr), { return Module.hiwire.new_value(AsciiToString(ptr)); }); -EM_JS(JsRef, hiwire_bytes, (char* ptr, int len), { +EM_JS_REF(JsRef, hiwire_bytes, (char* ptr, int len), { var bytes = new Uint8ClampedArray(Module.HEAPU8.buffer, ptr, len); return Module.hiwire.new_value(bytes); }); -EM_JS(JsRef, hiwire_int8array, (i8 * ptr, int len), { +EM_JS_REF(JsRef, hiwire_int8array, (i8 * ptr, int len), { var array = new Int8Array(Module.HEAPU8.buffer, ptr, len); return Module.hiwire.new_value(array); }) -EM_JS(JsRef, hiwire_uint8array, (u8 * ptr, int len), { +EM_JS_REF(JsRef, hiwire_uint8array, (u8 * ptr, int len), { var array = new Uint8Array(Module.HEAPU8.buffer, ptr, len); return Module.hiwire.new_value(array); }) -EM_JS(JsRef, hiwire_int16array, (i16 * ptr, int len), { +EM_JS_REF(JsRef, hiwire_int16array, (i16 * ptr, int len), { var array = new Int16Array(Module.HEAPU8.buffer, ptr, len); return Module.hiwire.new_value(array); }) -EM_JS(JsRef, hiwire_uint16array, (u16 * ptr, int len), { +EM_JS_REF(JsRef, hiwire_uint16array, (u16 * ptr, int len), { var array = new Uint16Array(Module.HEAPU8.buffer, ptr, len); return Module.hiwire.new_value(array); }) -EM_JS(JsRef, hiwire_int32array, (i32 * ptr, int len), { +EM_JS_REF(JsRef, hiwire_int32array, (i32 * ptr, int len), { var array = new Int32Array(Module.HEAPU8.buffer, ptr, len); return Module.hiwire.new_value(array); }) -EM_JS(JsRef, hiwire_uint32array, (u32 * ptr, int len), { +EM_JS_REF(JsRef, hiwire_uint32array, (u32 * ptr, int len), { var array = new Uint32Array(Module.HEAPU8.buffer, ptr, len); return Module.hiwire.new_value(array); }) -EM_JS(JsRef, hiwire_float32array, (f32 * ptr, int len), { +EM_JS_REF(JsRef, hiwire_float32array, (f32 * ptr, int len), { var array = new Float32Array(Module.HEAPU8.buffer, ptr, len); return Module.hiwire.new_value(array); }) -EM_JS(JsRef, hiwire_float64array, (f64 * ptr, int len), { +EM_JS_REF(JsRef, hiwire_float64array, (f64 * ptr, int len), { var array = new Float64Array(Module.HEAPU8.buffer, ptr, len); return Module.hiwire.new_value(array); }) -EM_JS(void, hiwire_throw_error, (JsRef idmsg), { +EM_JS_NUM(errcode, hiwire_throw_error, (JsRef idmsg), { var jsmsg = Module.hiwire.get_value(idmsg); Module.hiwire.decref(idmsg); throw new Error(jsmsg); }); -EM_JS(JsRef, hiwire_array, (), { return Module.hiwire.new_value([]); }); +EM_JS_REF(JsRef, hiwire_array, (), { return Module.hiwire.new_value([]); }); -EM_JS(void, hiwire_push_array, (JsRef idarr, JsRef idval), { +EM_JS_NUM(errcode, hiwire_push_array, (JsRef idarr, JsRef idval), { Module.hiwire.get_value(idarr).push(Module.hiwire.get_value(idval)); }); -EM_JS(JsRef, hiwire_object, (), { return Module.hiwire.new_value({}); }); +EM_JS_REF(JsRef, hiwire_object, (), { return Module.hiwire.new_value({}); }); -EM_JS(void, hiwire_push_object_pair, (JsRef idobj, JsRef idkey, JsRef idval), { - var jsobj = Module.hiwire.get_value(idobj); - var jskey = Module.hiwire.get_value(idkey); - var jsval = Module.hiwire.get_value(idval); - jsobj[jskey] = jsval; -}); +EM_JS_NUM(errcode, + hiwire_push_object_pair, + (JsRef idobj, JsRef idkey, JsRef idval), + { + var jsobj = Module.hiwire.get_value(idobj); + var jskey = Module.hiwire.get_value(idkey); + var jsval = Module.hiwire.get_value(idval); + jsobj[jskey] = jsval; + }); -EM_JS(JsRef, hiwire_get_global, (const char* ptrname), { +EM_JS_REF(JsRef, hiwire_get_global, (const char* ptrname), { var jsname = UTF8ToString(ptrname); if (jsname in self) { return Module.hiwire.new_value(self[jsname]); @@ -231,7 +239,7 @@ EM_JS(JsRef, hiwire_get_global, (const char* ptrname), { } }); -EM_JS(JsRef, hiwire_get_member_string, (JsRef idobj, const char* ptrkey), { +EM_JS_REF(JsRef, hiwire_get_member_string, (JsRef idobj, const char* ptrkey), { var jsobj = Module.hiwire.get_value(idobj); var jskey = UTF8ToString(ptrkey); if (jskey in jsobj) { @@ -241,32 +249,35 @@ EM_JS(JsRef, hiwire_get_member_string, (JsRef idobj, const char* ptrkey), { } }); -EM_JS(void, - hiwire_set_member_string, - (JsRef idobj, const char* ptrkey, JsRef idval), - { - var jsobj = Module.hiwire.get_value(idobj); - var jskey = UTF8ToString(ptrkey); - var jsval = Module.hiwire.get_value(idval); - jsobj[jskey] = jsval; - }); +EM_JS_NUM(errcode, + hiwire_set_member_string, + (JsRef idobj, const char* ptrkey, JsRef idval), + { + var jsobj = Module.hiwire.get_value(idobj); + var jskey = UTF8ToString(ptrkey); + var jsval = Module.hiwire.get_value(idval); + jsobj[jskey] = jsval; + }); -EM_JS(void, hiwire_delete_member_string, (JsRef idobj, const char* ptrkey), { - var jsobj = Module.hiwire.get_value(idobj); - var jskey = UTF8ToString(ptrkey); - delete jsobj[jskey]; -}); +EM_JS_NUM(errcode, + hiwire_delete_member_string, + (JsRef idobj, const char* ptrkey), + { + var jsobj = Module.hiwire.get_value(idobj); + var jskey = UTF8ToString(ptrkey); + delete jsobj[jskey]; + }); -EM_JS(JsRef, hiwire_get_member_int, (JsRef idobj, int idx), { +EM_JS_REF(JsRef, hiwire_get_member_int, (JsRef idobj, int idx), { var jsobj = Module.hiwire.get_value(idobj); return Module.hiwire.new_value(jsobj[idx]); }); -EM_JS(void, hiwire_set_member_int, (JsRef idobj, int idx, JsRef idval), { +EM_JS_NUM(errcode, hiwire_set_member_int, (JsRef idobj, int idx, JsRef idval), { Module.hiwire.get_value(idobj)[idx] = Module.hiwire.get_value(idval); }); -EM_JS(JsRef, hiwire_get_member_obj, (JsRef idobj, JsRef ididx), { +EM_JS_REF(JsRef, hiwire_get_member_obj, (JsRef idobj, JsRef ididx), { var jsobj = Module.hiwire.get_value(idobj); var jsidx = Module.hiwire.get_value(ididx); if (jsidx in jsobj) { @@ -276,20 +287,23 @@ EM_JS(JsRef, hiwire_get_member_obj, (JsRef idobj, JsRef ididx), { } }); -EM_JS(void, hiwire_set_member_obj, (JsRef idobj, JsRef ididx, JsRef idval), { - var jsobj = Module.hiwire.get_value(idobj); - var jsidx = Module.hiwire.get_value(ididx); - var jsval = Module.hiwire.get_value(idval); - jsobj[jsidx] = jsval; -}); +EM_JS_NUM(errcode, + hiwire_set_member_obj, + (JsRef idobj, JsRef ididx, JsRef idval), + { + var jsobj = Module.hiwire.get_value(idobj); + var jsidx = Module.hiwire.get_value(ididx); + var jsval = Module.hiwire.get_value(idval); + jsobj[jsidx] = jsval; + }); -EM_JS(void, hiwire_delete_member_obj, (JsRef idobj, JsRef ididx), { +EM_JS_NUM(errcode, hiwire_delete_member_obj, (JsRef idobj, JsRef ididx), { var jsobj = Module.hiwire.get_value(idobj); var jsidx = Module.hiwire.get_value(ididx); delete jsobj[jsidx]; }); -EM_JS(JsRef, hiwire_dir, (JsRef idobj), { +EM_JS_REF(JsRef, hiwire_dir, (JsRef idobj), { var jsobj = Module.hiwire.get_value(idobj); var result = []; do { @@ -298,23 +312,23 @@ EM_JS(JsRef, hiwire_dir, (JsRef idobj), { return Module.hiwire.new_value(result); }); -EM_JS(JsRef, hiwire_call, (JsRef idfunc, JsRef idargs), { +EM_JS_REF(JsRef, hiwire_call, (JsRef idfunc, JsRef idargs), { var jsfunc = Module.hiwire.get_value(idfunc); var jsargs = Module.hiwire.get_value(idargs); return Module.hiwire.new_value(jsfunc.apply(jsfunc, jsargs)); }); -EM_JS(JsRef, - hiwire_call_member, - (JsRef idobj, const char* ptrname, JsRef idargs), - { - var jsobj = Module.hiwire.get_value(idobj); - var jsname = UTF8ToString(ptrname); - var jsargs = Module.hiwire.get_value(idargs); - return Module.hiwire.new_value(jsobj[jsname].apply(jsobj, jsargs)); - }); +EM_JS_REF(JsRef, + hiwire_call_member, + (JsRef idobj, const char* ptrname, JsRef idargs), + { + var jsobj = Module.hiwire.get_value(idobj); + var jsname = UTF8ToString(ptrname); + var jsargs = Module.hiwire.get_value(idargs); + return Module.hiwire.new_value(jsobj[jsname].apply(jsobj, jsargs)); + }); -EM_JS(JsRef, hiwire_new, (JsRef idobj, JsRef idargs), { +EM_JS_REF(JsRef, hiwire_new, (JsRef idobj, JsRef idargs), { function newCall(Cls) { return new (Function.prototype.bind.apply(Cls, arguments)); @@ -325,37 +339,37 @@ EM_JS(JsRef, hiwire_new, (JsRef idobj, JsRef idargs), { return Module.hiwire.new_value(newCall.apply(newCall, jsargs)); }); -EM_JS(int, hiwire_get_length, (JsRef idobj), { +EM_JS_NUM(int, hiwire_get_length, (JsRef idobj), { return Module.hiwire.get_value(idobj).length; }); -EM_JS(bool, hiwire_get_bool, (JsRef idobj), { +EM_JS_NUM(bool, hiwire_get_bool, (JsRef idobj), { var val = Module.hiwire.get_value(idobj); // clang-format off return (val && (val.length === undefined || val.length)) ? 1 : 0; // clang-format on }); -EM_JS(bool, hiwire_is_function, (JsRef idobj), { +EM_JS_NUM(bool, hiwire_is_function, (JsRef idobj), { // clang-format off return typeof Module.hiwire.get_value(idobj) === 'function'; // clang-format on }); -EM_JS(JsRef, hiwire_to_string, (JsRef idobj), { +EM_JS_REF(JsRef, hiwire_to_string, (JsRef idobj), { return Module.hiwire.new_value(Module.hiwire.get_value(idobj).toString()); }); -EM_JS(JsRef, hiwire_typeof, (JsRef idobj), { +EM_JS_REF(JsRef, hiwire_typeof, (JsRef idobj), { return Module.hiwire.new_value(typeof Module.hiwire.get_value(idobj)); }); -EM_JS(char*, hiwire_constructor_name, (JsRef idobj), { +EM_JS_REF(char*, hiwire_constructor_name, (JsRef idobj), { return stringToNewUTF8(Module.hiwire.get_value(idobj).constructor.name); }); #define MAKE_OPERATOR(name, op) \ - EM_JS(bool, hiwire_##name, (JsRef ida, JsRef idb), { \ + EM_JS_NUM(bool, hiwire_##name, (JsRef ida, JsRef idb), { \ return (Module.hiwire.get_value(ida) op Module.hiwire.get_value(idb)) ? 1 \ : 0; \ }) @@ -367,7 +381,7 @@ MAKE_OPERATOR(not_equal, !=); MAKE_OPERATOR(greater_than, >); MAKE_OPERATOR(greater_than_equal, >=); -EM_JS(JsRef, hiwire_next, (JsRef idobj), { +EM_JS_REF(JsRef, hiwire_next, (JsRef idobj), { // clang-format off if (idobj === Module.hiwire.UNDEFINED) { return Module.hiwire.ERROR; @@ -378,7 +392,7 @@ EM_JS(JsRef, hiwire_next, (JsRef idobj), { // clang-format on }); -EM_JS(JsRef, hiwire_get_iterator, (JsRef idobj), { +EM_JS_REF(JsRef, hiwire_get_iterator, (JsRef idobj), { // clang-format off if (idobj === Module.hiwire.UNDEFINED) { return Module.hiwire.ERROR; @@ -396,37 +410,37 @@ EM_JS(JsRef, hiwire_get_iterator, (JsRef idobj), { // clang-format on }) -EM_JS(bool, hiwire_nonzero, (JsRef idobj), { +EM_JS_NUM(bool, hiwire_nonzero, (JsRef idobj), { var jsobj = Module.hiwire.get_value(idobj); // TODO: should this be !== 0? return (jsobj != 0) ? 1 : 0; }); -EM_JS(bool, hiwire_is_typedarray, (JsRef idobj), { +EM_JS_NUM(bool, hiwire_is_typedarray, (JsRef idobj), { var jsobj = Module.hiwire.get_value(idobj); // clang-format off return (jsobj['byteLength'] !== undefined) ? 1 : 0; // clang-format on }); -EM_JS(bool, hiwire_is_on_wasm_heap, (JsRef idobj), { +EM_JS_NUM(bool, hiwire_is_on_wasm_heap, (JsRef idobj), { var jsobj = Module.hiwire.get_value(idobj); // clang-format off return (jsobj.buffer === Module.HEAPU8.buffer) ? 1 : 0; // clang-format on }); -EM_JS(int, hiwire_get_byteOffset, (JsRef idobj), { +EM_JS_NUM(int, hiwire_get_byteOffset, (JsRef idobj), { var jsobj = Module.hiwire.get_value(idobj); return jsobj['byteOffset']; }); -EM_JS(int, hiwire_get_byteLength, (JsRef idobj), { +EM_JS_NUM(int, hiwire_get_byteLength, (JsRef idobj), { var jsobj = Module.hiwire.get_value(idobj); return jsobj['byteLength']; }); -EM_JS(void, hiwire_copy_to_ptr, (JsRef idobj, void* ptr), { +EM_JS_NUM(errcode, hiwire_copy_to_ptr, (JsRef idobj, void* ptr), { var jsobj = Module.hiwire.get_value(idobj); // clang-format off var buffer = (jsobj['buffer'] !== undefined) ? jsobj.buffer : jsobj; @@ -434,34 +448,34 @@ EM_JS(void, hiwire_copy_to_ptr, (JsRef idobj, void* ptr), { Module.HEAPU8.set(new Uint8Array(buffer), ptr); }); -EM_JS(void, - hiwire_get_dtype, - (JsRef idobj, char** format_ptr, Py_ssize_t* size_ptr), - { - if (!Module.hiwire.dtype_map) { - let alloc = stringToNewUTF8; - Module.hiwire.dtype_map = new Map([ - [ 'Int8Array', [ alloc('b'), 1 ] ], - [ 'Uint8Array', [ alloc('B'), 1 ] ], - [ 'Uint8ClampedArray', [ alloc('B'), 1 ] ], - [ 'Int16Array', [ alloc('h'), 2 ] ], - [ 'Uint16Array', [ alloc('H'), 2 ] ], - [ 'Int32Array', [ alloc('i'), 4 ] ], - [ 'Uint32Array', [ alloc('I'), 4 ] ], - [ 'Float32Array', [ alloc('f'), 4 ] ], - [ 'Float64Array', [ alloc('d'), 8 ] ], - [ 'ArrayBuffer', [ alloc('B'), 1 ] ], // Default to Uint8; - ]); - } - let jsobj = Module.hiwire.get_value(idobj); - let[format_utf8, size] = - Module.hiwire.dtype_map.get(jsobj.constructor.name) || [ 0, 0 ]; - // Store results into arguments - setValue(format_ptr, format_utf8, "i8*"); - setValue(size_ptr, size, "i32"); - }); +EM_JS_NUM(errcode, + hiwire_get_dtype, + (JsRef idobj, char** format_ptr, Py_ssize_t* size_ptr), + { + if (!Module.hiwire.dtype_map) { + let alloc = stringToNewUTF8; + Module.hiwire.dtype_map = new Map([ + [ 'Int8Array', [ alloc('b'), 1 ] ], + [ 'Uint8Array', [ alloc('B'), 1 ] ], + [ 'Uint8ClampedArray', [ alloc('B'), 1 ] ], + [ 'Int16Array', [ alloc('h'), 2 ] ], + [ 'Uint16Array', [ alloc('H'), 2 ] ], + [ 'Int32Array', [ alloc('i'), 4 ] ], + [ 'Uint32Array', [ alloc('I'), 4 ] ], + [ 'Float32Array', [ alloc('f'), 4 ] ], + [ 'Float64Array', [ alloc('d'), 8 ] ], + [ 'ArrayBuffer', [ alloc('B'), 1 ] ], // Default to Uint8; + ]); + } + let jsobj = Module.hiwire.get_value(idobj); + let[format_utf8, size] = + Module.hiwire.dtype_map.get(jsobj.constructor.name) || [ 0, 0 ]; + // Store results into arguments + setValue(format_ptr, format_utf8, "i8*"); + setValue(size_ptr, size, "i32"); + }); -EM_JS(JsRef, hiwire_subarray, (JsRef idarr, int start, int end), { +EM_JS_REF(JsRef, hiwire_subarray, (JsRef idarr, int start, int end), { var jsarr = Module.hiwire.get_value(idarr); var jssub = jsarr.subarray(start, end); return Module.hiwire.new_value(jssub); diff --git a/src/core/hiwire.h b/src/core/hiwire.h index 7b988e122..7b2ee0f2d 100644 --- a/src/core/hiwire.h +++ b/src/core/hiwire.h @@ -32,6 +32,9 @@ struct _JsRefStruct typedef struct _JsRefStruct* JsRef; +// Error handling will want to see JsRef. +#include "error_handling.h" + // Special JsRefs for singleton constants. // (These must be even because the least significance bit is set to 0 for // singleton constants.) @@ -57,7 +60,7 @@ hiwire_incref(JsRef idval); /** * Decrease the reference count on an object. */ -void +errcode hiwire_decref(JsRef idval); /** @@ -276,7 +279,7 @@ hiwire_array(); * If the user no longer needs the value outside of the array, it is the user's * responsibility to decref it. */ -void +errcode hiwire_push_array(JsRef idobj, JsRef idval); /** @@ -293,7 +296,7 @@ hiwire_object(); * If the user no longer needs the key or value outside of the object, it is the * user's responsibility to decref them. */ -void +errcode hiwire_push_object_pair(JsRef idobj, JsRef idkey, JsRef idval); /** @@ -302,7 +305,7 @@ hiwire_push_object_pair(JsRef idobj, JsRef idkey, JsRef idval); * The message is conventionally a Javascript string, but that is not required. * TODO: should be hiwire_set_error. */ -void +errcode hiwire_throw_error(JsRef idmsg); /** @@ -325,14 +328,14 @@ hiwire_get_member_string(JsRef idobj, const char* ptrname); /** * Set an object member by string. */ -void +errcode hiwire_set_member_string(JsRef idobj, const char* ptrname, JsRef idval); /** * Delete an object member by string. * */ -void +errcode hiwire_delete_member_string(JsRef idobj, const char* ptrname); /** @@ -351,7 +354,7 @@ hiwire_get_member_int(JsRef idobj, int idx); * The integer is a C integer, not an id reference to a Javascript integer. * */ -void +errcode hiwire_set_member_int(JsRef idobj, int idx, JsRef idval); /** @@ -366,14 +369,14 @@ hiwire_get_member_obj(JsRef idobj, JsRef ididx); * Set an object member by object. * */ -void +errcode hiwire_set_member_obj(JsRef idobj, JsRef ididx, JsRef idval); /** * Delete an object member by object. * */ -void +errcode hiwire_delete_member_obj(JsRef idobj, JsRef ididx); /** @@ -554,13 +557,13 @@ hiwire_get_byteOffset(JsRef idobj); * Copies the buffer contents of a given typed array or buffer into the memory * at ptr. */ -void +errcode hiwire_copy_to_ptr(JsRef idobj, void* ptr); /** * Get a data type identifier for a given typedarray. */ -void +errcode hiwire_get_dtype(JsRef idobj, char** format_ptr, Py_ssize_t* size_ptr); /** diff --git a/src/core/js2python.c b/src/core/js2python.c index 3dec1afb7..9d0c3aef7 100644 --- a/src/core/js2python.c +++ b/src/core/js2python.c @@ -1,4 +1,5 @@ #include "js2python.h" +#include "error_handling.h" #include @@ -79,8 +80,7 @@ _js2python_error(JsRef id) } // TODO: Add some meaningful order - -EM_JS(PyObject*, __js2python, (JsRef id), { +EM_JS_REF(PyObject*, __js2python, (JsRef id), { function __js2python_string(value) { // The general idea here is to allocate a Python string and then diff --git a/src/core/main.c b/src/core/main.c index e6e48030f..8dd51e675 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -3,6 +3,7 @@ #include #include +#include "error_handling.h" #include "hiwire.h" #include "js2python.h" #include "jsimport.h" @@ -59,6 +60,7 @@ main(int argc, char** argv) } Py_DECREF(sys); + TRY_INIT(error_handling); TRY_INIT(js2python); TRY_INIT(JsImport); TRY_INIT(JsProxy); diff --git a/src/core/pyproxy.c b/src/core/pyproxy.c index a4dda3c91..f77ae9675 100644 --- a/src/core/pyproxy.c +++ b/src/core/pyproxy.c @@ -1,3 +1,4 @@ +#include "error_handling.h" #include #include @@ -144,7 +145,7 @@ _pyproxy_destroy(PyObject* ptrobj) EM_ASM(delete Module.PyProxies[ptrobj];); } -EM_JS(JsRef, pyproxy_use, (PyObject * ptrobj), { +EM_JS_REF(JsRef, pyproxy_use, (PyObject * ptrobj), { // Checks if there is already an existing proxy on ptrobj if (Module.PyProxies.hasOwnProperty(ptrobj)) { @@ -154,7 +155,7 @@ EM_JS(JsRef, pyproxy_use, (PyObject * ptrobj), { return Module.hiwire.ERROR; }) -EM_JS(JsRef, pyproxy_new, (PyObject * ptrobj), { +EM_JS_REF(JsRef, pyproxy_new, (PyObject * ptrobj), { // Technically, this leaks memory, since we're holding on to a reference // to the proxy forever. But we have that problem anyway since we don't // have a destructor in Javascript to free the Python object. @@ -169,7 +170,7 @@ EM_JS(JsRef, pyproxy_new, (PyObject * ptrobj), { return Module.hiwire.new_value(proxy); }); -EM_JS(int, pyproxy_init, (), { +EM_JS_NUM(int, pyproxy_init, (), { // clang-format off Module.PyProxies = {}; Module.PyProxy = { diff --git a/src/core/runpython.c b/src/core/runpython.c index 46bf000d2..c10c57f8b 100644 --- a/src/core/runpython.c +++ b/src/core/runpython.c @@ -1,4 +1,5 @@ #include "runpython.h" +#include "error_handling.h" #include "hiwire.h" #include "pyproxy.h" #include "python2js.h" @@ -39,22 +40,25 @@ _runPythonDebug(char* code) return id; } -EM_JS(int, runpython_init_js, (JsRef pyodide_py_proxy, JsRef globals_proxy), { - Module.pyodide_py = Module.hiwire.get_value(pyodide_py_proxy); - Module.globals = Module.hiwire.get_value(globals_proxy); +EM_JS_NUM(int, + runpython_init_js, + (JsRef pyodide_py_proxy, JsRef globals_proxy), + { + Module.pyodide_py = Module.hiwire.get_value(pyodide_py_proxy); + Module.globals = Module.hiwire.get_value(globals_proxy); - // Use this to test python code separate from pyproxy.apply. - Module.runPythonDebug = function(code) - { - let pycode = stringToNewUTF8(code); - let idresult = Module.__runPythonDebug(pycode); - let jsresult = Module.hiwire.get_value(idresult); - Module.hiwire.decref(idresult); - _free(pycode); - return jsresult; - }; - return 0; -}); + // Use this to test python code separate from pyproxy.apply. + Module.runPythonDebug = function(code) + { + let pycode = stringToNewUTF8(code); + let idresult = Module.__runPythonDebug(pycode); + let jsresult = Module.hiwire.get_value(idresult); + Module.hiwire.decref(idresult); + _free(pycode); + return jsresult; + }; + return 0; + }); #define QUIT_IF_NULL(x) \ do { \ diff --git a/src/core/types.h b/src/core/types.h index c4edae244..479034065 100644 --- a/src/core/types.h +++ b/src/core/types.h @@ -4,6 +4,16 @@ #include "stdbool.h" #include "stdint.h" +#undef false +#undef true +// These work for both C and javascript. +// In C !!0 ==> 0 and in javascript !!0 ==> false +// In C !!1 ==> 1 and in javascript !!1 ==> true +// clang-format off +#define false (!!0) +#define true (!!1) +// clang-format on + typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; @@ -15,4 +25,5 @@ typedef int64_t i64; typedef float f32; typedef double f64; + #endif /* MY_LINUX_TYPES_H */