22
33#include "third-party/quickjs.h"
44
5- static PyObject * JSException = NULL ;
5+ static PyObject * JSException = NULL ;
6+ static PyObject * quickjs_to_python (JSContext * context , JSValue value );
67
7- static PyObject * quickjs_to_python (JSContext * context , JSValue value ) {
8- int tag = JS_VALUE_GET_TAG (value );
8+ //
9+ // Object type
10+ //
11+
12+ typedef struct {
13+ PyObject_HEAD ;
14+ JSContext * context ;
15+ JSValue object ;
16+ } ObjectData ;
17+
18+ static PyObject * object_new (PyTypeObject * type , PyObject * args , PyObject * kwds ) {
19+ ObjectData * self ;
20+ self = (ObjectData * )type -> tp_alloc (type , 0 );
21+ if (self != NULL ) {
22+ self -> context = NULL ;
23+ }
24+ return (PyObject * )self ;
25+ }
26+
27+ static void object_dealloc (ObjectData * self ) {
28+ Py_TYPE (self )-> tp_free ((PyObject * )self );
29+ }
30+
31+ static PyObject * object_call (ObjectData * self , PyObject * args ) {
32+ if (self -> context ) {
33+ JS_FreeValue (self -> context , self -> object );
34+ }
35+ Py_RETURN_NONE ;
36+ }
37+
38+ static PyMethodDef object_methods [] = {
39+ {"call" , (PyCFunction )object_call , METH_VARARGS , "Calls a JS function." }, {NULL } /* Sentinel */
40+ };
41+
42+ static PyTypeObject Object = {PyVarObject_HEAD_INIT (NULL , 0 ).tp_name = "_quickjs.Object" ,
43+ .tp_doc = "Quickjs object" ,
44+ .tp_basicsize = sizeof (ObjectData ),
45+ .tp_itemsize = 0 ,
46+ .tp_flags = Py_TPFLAGS_DEFAULT ,
47+ .tp_new = object_new ,
48+ .tp_dealloc = (destructor )object_dealloc ,
49+ .tp_methods = object_methods };
50+
51+ static PyObject * quickjs_to_python (JSContext * context , JSValue value ) {
52+ int tag = JS_VALUE_GET_TAG (value );
953PyObject * return_value = NULL ;
1054
1155if (tag == JS_TAG_INT ) {
@@ -19,21 +63,27 @@ static PyObject* quickjs_to_python(JSContext* context, JSValue value) {
1963} else if (tag == JS_TAG_UNINITIALIZED ) {
2064return_value = Py_None ;
2165} else if (tag == JS_TAG_EXCEPTION ) {
22- JSValue exception = JS_GetException (context );
23- JSValue error_string = JS_ToString (context , exception );
24- const char * cstring = JS_ToCString (context , error_string );
25- PyErr_Format (JSException , "%s" , cstring );
66+ JSValue exception = JS_GetException (context );
67+ JSValue error_string = JS_ToString (context , exception );
68+ const char * cstring = JS_ToCString (context , error_string );
69+ PyErr_Format (JSException , "%s" , cstring );
2670JS_FreeCString (context , cstring );
27- JS_FreeValue (context , error_string );
28- JS_FreeValue (context , exception );
71+ JS_FreeValue (context , error_string );
72+ JS_FreeValue (context , exception );
2973} else if (tag == JS_TAG_FLOAT64 ) {
3074return_value = Py_BuildValue ("d" , JS_VALUE_GET_FLOAT64 (value ));
3175} else if (tag == JS_TAG_STRING ) {
3276const char * cstring = JS_ToCString (context , value );
3377return_value = Py_BuildValue ("s" , cstring );
3478JS_FreeCString (context , cstring );
79+ } else if (tag == JS_TAG_OBJECT ) {
80+ return_value = PyObject_CallObject ((PyObject * )& Object , NULL );
81+ ObjectData * object = (ObjectData * )return_value ;
82+ object -> context = context ;
83+ object -> object = value ;
84+ return return_value ;
3585} else {
36- // TODO: Raise exception.
86+ PyErr_Format ( PyExc_ValueError , "Unknown quickjs tag: %d" , tag );
3787}
3888
3989JS_FreeValue (context , value );
@@ -49,6 +99,9 @@ static PyObject *test(PyObject *self, PyObject *args) {
4999
50100struct module_state {};
51101
102+ //
103+ // Context type
104+ //
52105typedef struct {
53106PyObject_HEAD JSRuntime * runtime ;
54107JSContext * context ;
@@ -76,7 +129,7 @@ static PyObject *context_eval(ContextData *self, PyObject *args) {
76129return NULL ;
77130}
78131JSValue value = JS_Eval (self -> context , code , strlen (code ), "<input>" , JS_EVAL_TYPE_GLOBAL );
79- return quickjs_to_python (self -> context , value );
132+ return quickjs_to_python (self -> context , value );
80133}
81134
82135static PyMethodDef context_methods [] = {
@@ -110,19 +163,24 @@ PyMODINIT_FUNC PyInit__quickjs(void) {
110163if (PyType_Ready (& Context ) < 0 ) {
111164return NULL ;
112165}
166+ if (PyType_Ready (& Object ) < 0 ) {
167+ return NULL ;
168+ }
113169
114170PyObject * module = PyModule_Create (& moduledef );
115171if (module == NULL ) {
116172return NULL ;
117173}
118174
119- JSException = PyErr_NewException ("_quickjs.JSException" , NULL , NULL );
120- if (JSException == NULL ) {
121- return NULL ;
122- }
175+ JSException = PyErr_NewException ("_quickjs.JSException" , NULL , NULL );
176+ if (JSException == NULL ) {
177+ return NULL ;
178+ }
123179
124180Py_INCREF (& Context );
125181PyModule_AddObject (module , "Context" , (PyObject * )& Context );
126- PyModule_AddObject (module , "JSException" , JSException );
182+ Py_INCREF (& Object );
183+ PyModule_AddObject (module , "Object" , (PyObject * )& Object );
184+ PyModule_AddObject (module , "JSException" , JSException );
127185return module ;
128186}
0 commit comments