forked from Distributive-Network/PythonMonkey
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJSMethodProxy.cc
More file actions
78 lines (64 loc) · 2.34 KB
/
JSMethodProxy.cc
File metadata and controls
78 lines (64 loc) · 2.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/**
* @file JSMethodProxy.cc
* @author Caleb Aikens (caleb@distributive.network)
* @brief JSMethodProxy is a custom C-implemented python type. It acts as a proxy for JSFunctions from Spidermonkey, and behaves like a method would, treating `self` as `this`.
* @date 2023-11-14
*
* @copyright Copyright (c) 2023 Distributive Corp.
*
*/
#include "include/JSMethodProxy.hh"
#include "include/modules/pythonmonkey/pythonmonkey.hh"
#include "include/jsTypeFactory.hh"
#include "include/pyTypeFactory.hh"
#include "include/setSpiderMonkeyException.hh"
#include <jsapi.h>
#include <Python.h>
void JSMethodProxyMethodDefinitions::JSMethodProxy_dealloc(JSMethodProxy *self)
{
delete self->jsFunc;
return;
}
PyObject *JSMethodProxyMethodDefinitions::JSMethodProxy_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) {
JSFunctionProxy *jsFunctionProxy;
PyObject *im_self;
if (!PyArg_ParseTuple(args, "O!O", &JSFunctionProxyType, &jsFunctionProxy, &im_self)) {
return NULL;
}
JSMethodProxy *self = (JSMethodProxy *)subtype->tp_alloc(subtype, 0);
if (self) {
self->self = im_self;
self->jsFunc = new JS::PersistentRootedObject(GLOBAL_CX);
self->jsFunc->set(*(jsFunctionProxy->jsFunc));
}
return (PyObject *)self;
}
PyObject *JSMethodProxyMethodDefinitions::JSMethodProxy_call(PyObject *self, PyObject *args, PyObject *kwargs) {
JSContext *cx = GLOBAL_CX;
JS::RootedValue jsFunc(GLOBAL_CX, JS::ObjectValue(**((JSMethodProxy *)self)->jsFunc));
JS::RootedValue selfValue(cx, jsTypeFactory(cx, ((JSMethodProxy *)self)->self));
JS::RootedObject selfObject(cx);
JS_ValueToObject(cx, selfValue, &selfObject);
JS::RootedVector<JS::Value> jsArgsVector(cx);
for (size_t i = 0; i < PyTuple_Size(args); i++) {
JS::Value jsValue = jsTypeFactory(cx, PyTuple_GetItem(args, i));
if (PyErr_Occurred()) { // Check if an exception has already been set in the flow of control
return NULL; // Fail-fast
}
if (!jsArgsVector.append(jsValue)) {
// out of memory
setSpiderMonkeyException(cx);
return NULL;
}
}
JS::HandleValueArray jsArgs(jsArgsVector);
JS::RootedValue jsReturnVal(cx);
if (!JS_CallFunctionValue(cx, selfObject, jsFunc, jsArgs, &jsReturnVal)) {
setSpiderMonkeyException(cx);
return NULL;
}
if (PyErr_Occurred()) {
return NULL;
}
return pyTypeFactory(cx, jsReturnVal);
}