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 );
953 PyObject * return_value = NULL ;
1054
1155 if (tag == JS_TAG_INT ) {
@@ -19,21 +63,27 @@ static PyObject* quickjs_to_python(JSContext* context, JSValue value) {
1963 } else if (tag == JS_TAG_UNINITIALIZED ) {
2064 return_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 );
2670 JS_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 ) {
3074 return_value = Py_BuildValue ("d" , JS_VALUE_GET_FLOAT64 (value ));
3175 } else if (tag == JS_TAG_STRING ) {
3276 const char * cstring = JS_ToCString (context , value );
3377 return_value = Py_BuildValue ("s" , cstring );
3478 JS_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
3989 JS_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 {
53106 PyObject_HEAD JSRuntime * runtime ;
54107 JSContext * context ;
@@ -76,7 +129,7 @@ static PyObject *context_eval(ContextData *self, PyObject *args) {
76129 return NULL ;
77130 }
78131 JSValue 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) {
110163 if (PyType_Ready (& Context ) < 0 ) {
111164 return NULL ;
112165 }
166+ if (PyType_Ready (& Object ) < 0 ) {
167+ return NULL ;
168+ }
113169
114170 PyObject * module = PyModule_Create (& moduledef );
115171 if (module == NULL ) {
116172 return 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
124180 Py_INCREF (& Context );
125181 PyModule_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 );
127185 return module ;
128186}
0 commit comments