-
Notifications
You must be signed in to change notification settings - Fork 43
Expand file tree
/
Copy pathPyDictProxyHandler.cc
More file actions
111 lines (90 loc) · 3.59 KB
/
PyDictProxyHandler.cc
File metadata and controls
111 lines (90 loc) · 3.59 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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/**
* @file PyDictProxyHandler.cc
* @author Caleb Aikens (caleb@distributive.network) and Philippe Laporte (philippe@distributive.network)
* @brief Struct for creating JS proxy objects for Dicts
* @date 2023-04-20
*
* @copyright Copyright (c) 2023-2024 Distributive Corp.
*
*/
#include "include/PyDictProxyHandler.hh"
#include "include/jsTypeFactory.hh"
#include "include/pyTypeFactory.hh"
#include <jsapi.h>
#include <jsfriendapi.h>
#include <js/Conversions.h>
#include <js/Proxy.h>
#include <js/Symbol.h>
#include <js/friend/ErrorMessages.h>
#include <Python.h>
const char PyDictProxyHandler::family = 0;
bool PyDictProxyHandler::ownPropertyKeys(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleIdVector props) const {
PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot);
PyObject *keys = PyDict_Keys(self);
size_t length = PyList_Size(keys);
return handleOwnPropertyKeys(cx, keys, length, props);
}
bool PyDictProxyHandler::delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
JS::ObjectOpResult &result) const {
PyObject *attrName = idToKey(cx, id);
PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot);
if (PyDict_DelItem(self, attrName) < 0) {
return result.failCantDelete(); // raises JS exception
}
return result.succeed();
}
bool PyDictProxyHandler::has(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
bool *bp) const {
return hasOwn(cx, proxy, id, bp);
}
bool PyDictProxyHandler::getOwnPropertyDescriptor(
JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> desc
) const {
PyObject *attrName = idToKey(cx, id);
PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot);
PyObject *item = PyDict_GetItemWithError(self, attrName); // returns NULL without an exception set if the key wasn’t present.
return handleGetOwnPropertyDescriptor(cx, id, desc, item);
}
bool PyDictProxyHandler::set(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
JS::HandleValue v, JS::HandleValue receiver,
JS::ObjectOpResult &result) const {
JS::RootedValue rootedV(cx, v);
PyObject *attrName = idToKey(cx, id);
PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot);
PyObject *value = pyTypeFactory(cx, rootedV);
if (PyDict_SetItem(self, attrName, value)) {
Py_DECREF(value);
return result.failCantSetInterposed(); // raises JS exception
}
Py_DECREF(value);
return result.succeed();
}
bool PyDictProxyHandler::enumerate(JSContext *cx, JS::HandleObject proxy,
JS::MutableHandleIdVector props) const {
return this->ownPropertyKeys(cx, proxy, props);
}
bool PyDictProxyHandler::hasOwn(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
bool *bp) const {
PyObject *attrName = idToKey(cx, id);
PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot);
*bp = PyDict_Contains(self, attrName) == 1;
return true;
}
bool PyDictProxyHandler::getOwnEnumerablePropertyKeys(
JSContext *cx, JS::HandleObject proxy,
JS::MutableHandleIdVector props) const {
return this->ownPropertyKeys(cx, proxy, props);
}
bool PyDictProxyHandler::defineProperty(JSContext *cx, JS::HandleObject proxy,
JS::HandleId id,
JS::Handle<JS::PropertyDescriptor> desc,
JS::ObjectOpResult &result) const {
// Block direct `Object.defineProperty` since we already have the `set` method
return result.failInvalidDescriptor();
}
bool PyDictProxyHandler::getBuiltinClass(JSContext *cx, JS::HandleObject proxy,
js::ESClass *cls) const {
*cls = js::ESClass::Object;
return true;
}