Skip to content

Commit 513c47e

Browse files
committed
Allow passing Object when calling an Object.
1 parent c19d480 commit 513c47e

File tree

2 files changed

+43
-26
lines changed

2 files changed

+43
-26
lines changed

module.c

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,34 @@ static void object_dealloc(ObjectData *self) {
3131
Py_TYPE(self)->tp_free((PyObject *)self);
3232
}
3333

34+
static PyObject *object_call(ObjectData *self, PyObject *args, PyObject *kwds);
35+
36+
static PyObject *object_json(ObjectData *self) {
37+
JSValue global = JS_GetGlobalObject(self->context);
38+
JSValue JSON = JS_GetPropertyStr(self->context, global, "JSON");
39+
JSValue stringify = JS_GetPropertyStr(self->context, JSON, "stringify");
40+
JSValueConst args[1] = {self->object};
41+
JSValue json_string = JS_Call(self->context, stringify, JSON, 1, args);
42+
JS_FreeValue(self->context, global);
43+
JS_FreeValue(self->context, JSON);
44+
JS_FreeValue(self->context, stringify);
45+
return quickjs_to_python(self->context, json_string);
46+
}
47+
48+
static PyMethodDef object_methods[] = {
49+
{"json", object_json, METH_NOARGS, "Converts to a JSON string."}, {NULL} /* Sentinel */
50+
};
51+
52+
static PyTypeObject Object = {PyVarObject_HEAD_INIT(NULL, 0).tp_name = "_quickjs.Object",
53+
.tp_doc = "Quickjs object",
54+
.tp_basicsize = sizeof(ObjectData),
55+
.tp_itemsize = 0,
56+
.tp_flags = Py_TPFLAGS_DEFAULT,
57+
.tp_new = object_new,
58+
.tp_dealloc = (destructor)object_dealloc,
59+
.tp_call = object_call,
60+
.tp_methods = object_methods};
61+
3462
static PyObject *object_call(ObjectData *self, PyObject *args, PyObject *kwds) {
3563
if (self->context == NULL) {
3664
Py_RETURN_NONE;
@@ -40,6 +68,7 @@ static PyObject *object_call(ObjectData *self, PyObject *args, PyObject *kwds) {
4068
PyObject *item = PyTuple_GetItem(args, i);
4169
if (PyLong_Check(item)) {
4270
} else if (PyUnicode_Check(item)) {
71+
} else if (PyObject_IsInstance(item, &Object)) {
4372
} else {
4473
PyErr_Format(PyExc_ValueError, "Unsupported type when calling quickjs object");
4574
return NULL;
@@ -52,6 +81,8 @@ static PyObject *object_call(ObjectData *self, PyObject *args, PyObject *kwds) {
5281
jsargs[i] = JS_MKVAL(JS_TAG_INT, PyLong_AsLong(item));
5382
} else if (PyUnicode_Check(item)) {
5483
jsargs[i] = JS_NewString(self->context, PyUnicode_AsUTF8(item));
84+
} else if (PyObject_IsInstance(item, &Object)) {
85+
jsargs[i] = JS_DupValue(self->context, ((ObjectData *)item)->object);
5586
}
5687
}
5788
JSValue value = JS_Call(self->context, self->object, JS_NULL, nargs, jsargs);
@@ -62,32 +93,6 @@ static PyObject *object_call(ObjectData *self, PyObject *args, PyObject *kwds) {
6293
return quickjs_to_python(self->context, value);
6394
}
6495

65-
static PyObject *object_json(ObjectData *self) {
66-
JSValue global = JS_GetGlobalObject(self->context);
67-
JSValue JSON = JS_GetPropertyStr(self->context, global, "JSON");
68-
JSValue stringify = JS_GetPropertyStr(self->context, JSON, "stringify");
69-
JSValueConst args[1] = {self->object};
70-
JSValue json_string = JS_Call(self->context, stringify, JSON, 1, args);
71-
JS_FreeValue(self->context, global);
72-
JS_FreeValue(self->context, JSON);
73-
JS_FreeValue(self->context, stringify);
74-
return quickjs_to_python(self->context, json_string);
75-
}
76-
77-
static PyMethodDef object_methods[] = {
78-
{"json", object_json, METH_NOARGS, "Converts to a JSON string."}, {NULL} /* Sentinel */
79-
};
80-
81-
static PyTypeObject Object = {PyVarObject_HEAD_INIT(NULL, 0).tp_name = "_quickjs.Object",
82-
.tp_doc = "Quickjs object",
83-
.tp_basicsize = sizeof(ObjectData),
84-
.tp_itemsize = 0,
85-
.tp_flags = Py_TPFLAGS_DEFAULT,
86-
.tp_new = object_new,
87-
.tp_dealloc = (destructor)object_dealloc,
88-
.tp_call = object_call,
89-
.tp_methods = object_methods};
90-
9196
static PyObject *quickjs_to_python(JSContext *context, JSValue value) {
9297
int tag = JS_VALUE_GET_TAG(value);
9398
PyObject *return_value = NULL;

test_quickjs.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,18 @@ def test_function_call_str_three_args(self):
9696
""")
9797
self.assertEqual(f("1", "2", "3"), "1 hej 2 ho 3")
9898

99+
def test_function_call_object(self):
100+
d = self.context.eval("d = {data: 42};")
101+
f = self.context.eval("""
102+
f = function(d) {
103+
return d.data;
104+
}
105+
""")
106+
self.assertEqual(f(d), 42)
107+
# Try again to make sure refcounting works.
108+
self.assertEqual(f(d), 42)
109+
self.assertEqual(f(d), 42)
110+
99111
def test_function_call_unsupported_arg(self):
100112
f = self.context.eval("""
101113
f = function(x) {

0 commit comments

Comments
 (0)