Commit 27d135e6 authored by Roman Yurchak's avatar Roman Yurchak Committed by GitHub

Merge pull request #198 from mdboom/singleton-constants

Use constant hiwire ids for singleton values
parents a966927c fdab0249
#include <emscripten.h> #include <emscripten.h>
#include "hiwire.h"
// Define special ids for singleton constants. These must be less than -1 to
// avoid being reused for other values.
#define HW_UNDEFINED -2
#define HW_TRUE -3
#define HW_FALSE -4
#define HW_NULL -5
EM_JS(void, hiwire_setup, (), { EM_JS(void, hiwire_setup, (), {
// These ids must match the constants above, but we can't use them from JS
var hiwire = { objects : {}, counter : 1 }; var hiwire = { objects : {}, counter : 1 };
hiwire.objects[-2] = undefined;
hiwire.objects[-3] = true;
hiwire.objects[-4] = false;
hiwire.objects[-5] = null;
Module.hiwire_new_value = function(jsval) Module.hiwire_new_value = function(jsval)
{ {
...@@ -19,12 +33,18 @@ EM_JS(void, hiwire_setup, (), { ...@@ -19,12 +33,18 @@ EM_JS(void, hiwire_setup, (), {
Module.hiwire_decref = function(idval) Module.hiwire_decref = function(idval)
{ {
if (idval < 0) {
return;
}
var objects = hiwire.objects; var objects = hiwire.objects;
delete objects[idval]; delete objects[idval];
}; };
}); });
EM_JS(int, hiwire_incref, (int idval), { EM_JS(int, hiwire_incref, (int idval), {
if (idval < 0) {
return;
}
return Module.hiwire_new_value(Module.hiwire_get_value(idval)); return Module.hiwire_new_value(Module.hiwire_get_value(idval));
}); });
...@@ -76,15 +96,29 @@ EM_JS(int, hiwire_bytes, (int ptr, int len), { ...@@ -76,15 +96,29 @@ EM_JS(int, hiwire_bytes, (int ptr, int len), {
return Module.hiwire_new_value(bytes); return Module.hiwire_new_value(bytes);
}); });
EM_JS(int, hiwire_undefined, (), { int
return Module.hiwire_new_value(undefined); hiwire_undefined()
}); {
return HW_UNDEFINED;
}
EM_JS(int, hiwire_null, (), { return Module.hiwire_new_value(null); }); int
hiwire_null()
{
return HW_NULL;
}
EM_JS(int, hiwire_true, (), { return Module.hiwire_new_value(true); }); int
hiwire_true()
{
return HW_TRUE;
}
EM_JS(int, hiwire_false, (), { return Module.hiwire_new_value(false); }); int
hiwire_false()
{
return HW_FALSE;
}
EM_JS(void, hiwire_throw_error, (int idmsg), { EM_JS(void, hiwire_throw_error, (int idmsg), {
var jsmsg = Module.hiwire_get_value(idmsg); var jsmsg = Module.hiwire_get_value(idmsg);
...@@ -159,20 +193,20 @@ EM_JS(void, hiwire_delete_member_obj, (int idobj, int ididx), { ...@@ -159,20 +193,20 @@ EM_JS(void, hiwire_delete_member_obj, (int idobj, int ididx), {
delete jsobj[jsidx]; delete jsobj[jsidx];
}); });
EM_JS(void, hiwire_call, (int idfunc, int idargs), { EM_JS(int, hiwire_call, (int idfunc, int idargs), {
var jsfunc = Module.hiwire_get_value(idfunc); var jsfunc = Module.hiwire_get_value(idfunc);
var jsargs = Module.hiwire_get_value(idargs); var jsargs = Module.hiwire_get_value(idargs);
return Module.hiwire_new_value(jsfunc.apply(jsfunc, jsargs)); return Module.hiwire_new_value(jsfunc.apply(jsfunc, jsargs));
}); });
EM_JS(void, hiwire_call_member, (int idobj, int ptrname, int idargs), { EM_JS(int, hiwire_call_member, (int idobj, int ptrname, int idargs), {
var jsobj = Module.hiwire_get_value(idobj); var jsobj = Module.hiwire_get_value(idobj);
var jsname = UTF8ToString(ptrname); var jsname = UTF8ToString(ptrname);
var jsargs = Module.hiwire_get_value(idargs); var jsargs = Module.hiwire_get_value(idargs);
return Module.hiwire_new_value(jsobj[jsname].apply(jsobj, jsargs)); return Module.hiwire_new_value(jsobj[jsname].apply(jsobj, jsargs));
}); });
EM_JS(void, hiwire_new, (int idobj, int idargs), { EM_JS(int, hiwire_new, (int idobj, int idargs), {
function newCall(Cls) function newCall(Cls)
{ {
return new (Function.prototype.bind.apply(Cls, arguments)); return new (Function.prototype.bind.apply(Cls, arguments));
...@@ -219,7 +253,7 @@ EM_JS(int, hiwire_next, (int idobj), { ...@@ -219,7 +253,7 @@ EM_JS(int, hiwire_next, (int idobj), {
// clang-format off // clang-format off
if (jsobj.next === undefined) { if (jsobj.next === undefined) {
// clang-format on // clang-format on
return -1; return HW_ERROR;
} }
return Module.hiwire_new_value(jsobj.next()); return Module.hiwire_new_value(jsobj.next());
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
* object. There may be one or more keys pointing to the same object. * object. There may be one or more keys pointing to the same object.
*/ */
#define HW_ERROR -1
/** /**
* Initialize the variables and functions required for hiwire. * Initialize the variables and functions required for hiwire.
*/ */
...@@ -359,7 +361,7 @@ hiwire_greater_than_equal(int ida, int idb); ...@@ -359,7 +361,7 @@ hiwire_greater_than_equal(int ida, int idb);
/** /**
* Calls the `next` function on an iterator. * Calls the `next` function on an iterator.
* *
* Returns: -1 if `next` function is undefined. * Returns: HW_ERROR if `next` function is undefined.
*/ */
int int
hiwire_next(int idobj); hiwire_next(int idobj);
......
...@@ -17,7 +17,7 @@ pythonexc2js() ...@@ -17,7 +17,7 @@ pythonexc2js()
PyErr_Fetch(&type, &value, &traceback); PyErr_Fetch(&type, &value, &traceback);
PyErr_NormalizeException(&type, &value, &traceback); PyErr_NormalizeException(&type, &value, &traceback);
int excval = -1; int excval = HW_ERROR;
int exc; int exc;
if (type == NULL || type == Py_None || value == NULL || value == Py_None) { if (type == NULL || type == Py_None || value == NULL || value == Py_None) {
...@@ -86,7 +86,7 @@ exit: ...@@ -86,7 +86,7 @@ exit:
hiwire_throw_error(excval); hiwire_throw_error(excval);
return -1; return HW_ERROR;
} }
static int static int
...@@ -129,13 +129,13 @@ _python2js(PyObject* x, PyObject* map) ...@@ -129,13 +129,13 @@ _python2js(PyObject* x, PyObject* map)
} else if (PyLong_Check(x)) { } else if (PyLong_Check(x)) {
long x_long = PyLong_AsLongLong(x); long x_long = PyLong_AsLongLong(x);
if (x_long == -1 && PyErr_Occurred()) { if (x_long == -1 && PyErr_Occurred()) {
return -1; return HW_ERROR;
} }
return hiwire_int(x_long); return hiwire_int(x_long);
} else if (PyFloat_Check(x)) { } else if (PyFloat_Check(x)) {
double x_double = PyFloat_AsDouble(x); double x_double = PyFloat_AsDouble(x);
if (x_double == -1.0 && PyErr_Occurred()) { if (x_double == -1.0 && PyErr_Occurred()) {
return -1; return HW_ERROR;
} }
return hiwire_double(x_double); return hiwire_double(x_double);
} else if (PyUnicode_Check(x)) { } else if (PyUnicode_Check(x)) {
...@@ -151,13 +151,13 @@ _python2js(PyObject* x, PyObject* map) ...@@ -151,13 +151,13 @@ _python2js(PyObject* x, PyObject* map)
return hiwire_string_ucs4(data, length); return hiwire_string_ucs4(data, length);
default: default:
PyErr_SetString(PyExc_ValueError, "Unknown Unicode KIND"); PyErr_SetString(PyExc_ValueError, "Unknown Unicode KIND");
return -1; return HW_ERROR;
} }
} else if (PyBytes_Check(x)) { } else if (PyBytes_Check(x)) {
char* x_buff; char* x_buff;
Py_ssize_t length; Py_ssize_t length;
if (PyBytes_AsStringAndSize(x, &x_buff, &length)) { if (PyBytes_AsStringAndSize(x, &x_buff, &length)) {
return -1; return HW_ERROR;
} }
return hiwire_bytes((int)(void*)x_buff, length); return hiwire_bytes((int)(void*)x_buff, length);
} else if (JsProxy_Check(x)) { } else if (JsProxy_Check(x)) {
...@@ -166,7 +166,7 @@ _python2js(PyObject* x, PyObject* map) ...@@ -166,7 +166,7 @@ _python2js(PyObject* x, PyObject* map)
int jsarray = hiwire_array(); int jsarray = hiwire_array();
if (_python2js_add_to_cache(map, x, jsarray)) { if (_python2js_add_to_cache(map, x, jsarray)) {
hiwire_decref(jsarray); hiwire_decref(jsarray);
return -1; return HW_ERROR;
} }
size_t length = PySequence_Size(x); size_t length = PySequence_Size(x);
for (size_t i = 0; i < length; ++i) { for (size_t i = 0; i < length; ++i) {
...@@ -181,11 +181,11 @@ _python2js(PyObject* x, PyObject* map) ...@@ -181,11 +181,11 @@ _python2js(PyObject* x, PyObject* map)
return pyproxy_new((int)x); return pyproxy_new((int)x);
} }
int jsitem = _python2js_cache(pyitem, map); int jsitem = _python2js_cache(pyitem, map);
if (jsitem == -1) { if (jsitem == HW_ERROR) {
_python2js_remove_from_cache(map, x); _python2js_remove_from_cache(map, x);
Py_DECREF(pyitem); Py_DECREF(pyitem);
hiwire_decref(jsarray); hiwire_decref(jsarray);
return -1; return HW_ERROR;
} }
Py_DECREF(pyitem); Py_DECREF(pyitem);
hiwire_push_array(jsarray, jsitem); hiwire_push_array(jsarray, jsitem);
...@@ -193,30 +193,30 @@ _python2js(PyObject* x, PyObject* map) ...@@ -193,30 +193,30 @@ _python2js(PyObject* x, PyObject* map)
} }
if (_python2js_remove_from_cache(map, x)) { if (_python2js_remove_from_cache(map, x)) {
hiwire_decref(jsarray); hiwire_decref(jsarray);
return -1; return HW_ERROR;
} }
return jsarray; return jsarray;
} else if (PyDict_Check(x)) { } else if (PyDict_Check(x)) {
int jsdict = hiwire_object(); int jsdict = hiwire_object();
if (_python2js_add_to_cache(map, x, jsdict)) { if (_python2js_add_to_cache(map, x, jsdict)) {
hiwire_decref(jsdict); hiwire_decref(jsdict);
return -1; return HW_ERROR;
} }
PyObject *pykey, *pyval; PyObject *pykey, *pyval;
Py_ssize_t pos = 0; Py_ssize_t pos = 0;
while (PyDict_Next(x, &pos, &pykey, &pyval)) { while (PyDict_Next(x, &pos, &pykey, &pyval)) {
int jskey = _python2js_cache(pykey, map); int jskey = _python2js_cache(pykey, map);
if (jskey == -1) { if (jskey == HW_ERROR) {
_python2js_remove_from_cache(map, x); _python2js_remove_from_cache(map, x);
hiwire_decref(jsdict); hiwire_decref(jsdict);
return -1; return HW_ERROR;
} }
int jsval = _python2js_cache(pyval, map); int jsval = _python2js_cache(pyval, map);
if (jsval == -1) { if (jsval == HW_ERROR) {
_python2js_remove_from_cache(map, x); _python2js_remove_from_cache(map, x);
hiwire_decref(jskey); hiwire_decref(jskey);
hiwire_decref(jsdict); hiwire_decref(jsdict);
return -1; return HW_ERROR;
} }
hiwire_push_object_pair(jsdict, jskey, jsval); hiwire_push_object_pair(jsdict, jskey, jsval);
hiwire_decref(jskey); hiwire_decref(jskey);
...@@ -224,7 +224,7 @@ _python2js(PyObject* x, PyObject* map) ...@@ -224,7 +224,7 @@ _python2js(PyObject* x, PyObject* map)
} }
if (_python2js_remove_from_cache(map, x)) { if (_python2js_remove_from_cache(map, x)) {
hiwire_decref(jsdict); hiwire_decref(jsdict);
return -1; return HW_ERROR;
} }
return jsdict; return jsdict;
} else { } else {
...@@ -254,7 +254,7 @@ _python2js_add_to_cache(PyObject* map, PyObject* pyparent, int jsparent) ...@@ -254,7 +254,7 @@ _python2js_add_to_cache(PyObject* map, PyObject* pyparent, int jsparent)
if (PyDict_SetItem(map, pyparentid, jsparentid)) { if (PyDict_SetItem(map, pyparentid, jsparentid)) {
Py_DECREF(pyparentid); Py_DECREF(pyparentid);
Py_DECREF(jsparentid); Py_DECREF(jsparentid);
return -1; return HW_ERROR;
} }
Py_DECREF(pyparentid); Py_DECREF(pyparentid);
Py_DECREF(jsparentid); Py_DECREF(jsparentid);
...@@ -266,7 +266,7 @@ _python2js_remove_from_cache(PyObject* map, PyObject* pyparent) ...@@ -266,7 +266,7 @@ _python2js_remove_from_cache(PyObject* map, PyObject* pyparent)
{ {
PyObject* pyparentid = PyLong_FromSize_t((size_t)pyparent); PyObject* pyparentid = PyLong_FromSize_t((size_t)pyparent);
if (PyDict_DelItem(map, pyparentid)) { if (PyDict_DelItem(map, pyparentid)) {
return -1; return HW_ERROR;
} }
Py_DECREF(pyparentid); Py_DECREF(pyparentid);
return 0; return 0;
...@@ -280,7 +280,7 @@ _python2js_cache(PyObject* x, PyObject* map) ...@@ -280,7 +280,7 @@ _python2js_cache(PyObject* x, PyObject* map)
int result; int result;
if (val) { if (val) {
result = PyLong_AsLong(val); result = PyLong_AsLong(val);
if (result != -1) { if (result != HW_ERROR) {
result = hiwire_incref(result); result = hiwire_incref(result);
} }
Py_DECREF(val); Py_DECREF(val);
...@@ -298,7 +298,7 @@ python2js(PyObject* x) ...@@ -298,7 +298,7 @@ python2js(PyObject* x)
int result = _python2js_cache(x, map); int result = _python2js_cache(x, map);
Py_DECREF(map); Py_DECREF(map);
if (result == -1) { if (result == HW_ERROR) {
return pythonexc2js(); return pythonexc2js();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment