Skip to content

Commit de68174

Browse files
authored
Merge branch 'wes/module-system' into Xmader/feat/post-install-npm
2 parents 4fcd7b9 + fb7cb57 commit de68174

File tree

11 files changed

+331
-262
lines changed

11 files changed

+331
-262
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Copyright (c) 2022 Distributive Inc. All Rights Reserved.
22

3-
cmake_minimum_required(VERSION 3.4...3.18) # Set minimum cmake version
3+
cmake_minimum_required(VERSION 3.25) # Set minimum cmake version
44

55
project("PythonMonkey"
66
DESCRIPTION "A tool for Javascript-Python interoperability."

include/JSObjectProxy.hh

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,6 @@ public:
5757
*/
5858
static int JSObjectProxy_init(JSObjectProxy *self, PyObject *args, PyObject *kwds);
5959

60-
/**
61-
* @brief Helper function for JSObjectProxy_init
62-
*
63-
* @param jsObject - The underlying backing store JSObject for the JSObjectProxy
64-
* @param dict - The python dict to be converted into a JSObjectProxy
65-
* @param subValsMap - A map of PyObject to JS::Value pairs, representing values that have been visited so far
66-
*/
67-
static void JSObjectProxy_init_helper(JS::HandleObject jsObject, PyObject *dict, std::unordered_map<PyObject *, JS::RootedValue *> &subValsMap);
68-
6960
/**
7061
* @brief Length method (.mp_length), returns the number of key-value pairs in the JSObject, used by the python len() method
7162
*
@@ -121,16 +112,6 @@ public:
121112
* @return bool - Whether the compared objects are equal or not
122113
*/
123114
static bool JSObjectProxy_richcompare_helper(JSObjectProxy *self, PyObject *other, std::unordered_map<PyObject *, PyObject *> &visited);
124-
125-
/**
126-
* @brief Function to satisfy the python GC. See comment in function implementation for more details
127-
*
128-
* @param self - unused
129-
* @param visit - unused
130-
* @param arg - unused
131-
* @return int - always 0
132-
*/
133-
static int JSObjectProxy_traverse(JSObjectProxy *self, visitproc visit, void *arg);
134115
};
135116

136117

@@ -146,22 +127,5 @@ static PyMappingMethods JSObjectProxy_mapping_methods = {
146127

147128
/**
148129
* @brief Struct for the JSObjectProxyType, used by all JSObjectProxy objects
149-
*
150130
*/
151-
static PyTypeObject JSObjectProxyType = {
152-
.ob_base = PyVarObject_HEAD_INIT(&PyType_Type, 0)
153-
.tp_name = "pythonmonkey.JSObjectProxy",
154-
.tp_basicsize = sizeof(JSObjectProxy),
155-
.tp_dealloc = (destructor)JSObjectProxyMethodDefinitions::JSObjectProxy_dealloc,
156-
.tp_as_mapping = &JSObjectProxy_mapping_methods,
157-
.tp_getattro = (getattrofunc)JSObjectProxyMethodDefinitions::JSObjectProxy_get,
158-
.tp_setattro = (setattrofunc)JSObjectProxyMethodDefinitions::JSObjectProxy_assign,
159-
.tp_flags = Py_TPFLAGS_DEFAULT
160-
| Py_TPFLAGS_DICT_SUBCLASS, // https://docs.python.org/3/c-api/typeobj.html#Py_TPFLAGS_DICT_SUBCLASS
161-
.tp_doc = PyDoc_STR("Javascript Object proxy dict"),
162-
.tp_traverse = (traverseproc)JSObjectProxyMethodDefinitions::JSObjectProxy_traverse,
163-
.tp_richcompare = (richcmpfunc)JSObjectProxyMethodDefinitions::JSObjectProxy_richcompare,
164-
.tp_base = &PyDict_Type,
165-
.tp_init = (initproc)JSObjectProxyMethodDefinitions::JSObjectProxy_init,
166-
.tp_new = JSObjectProxyMethodDefinitions::JSObjectProxy_new,
167-
};
131+
extern PyTypeObject JSObjectProxyType;

include/PyProxyHandler.hh

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,26 @@
1717

1818
#include <Python.h>
1919

20+
/**
21+
* @brief base class for PyProxyHandler and PyListProxyHandler
22+
*/
23+
struct PyBaseProxyHandler : public js::BaseProxyHandler {
24+
public:
25+
PyBaseProxyHandler(PyObject *pyObj) : js::BaseProxyHandler(NULL), pyObject(pyObj) {};
26+
PyObject *pyObject; // @TODO (Caleb Aikens) Consider putting this in a private slot
27+
28+
bool getPrototypeIfOrdinary(JSContext *cx, JS::HandleObject proxy, bool *isOrdinary, JS::MutableHandleObject protop) const override final;
29+
bool preventExtensions(JSContext *cx, JS::HandleObject proxy, JS::ObjectOpResult &result) const override final;
30+
bool isExtensible(JSContext *cx, JS::HandleObject proxy, bool *extensible) const override final;
31+
};
32+
2033
/**
2134
* @brief This struct is the ProxyHandler for JS Proxy Objects pythonmonkey creates to handle coercion from python dicts to JS Objects
2235
*
2336
*/
24-
struct PyProxyHandler : public js::BaseProxyHandler {
37+
struct PyProxyHandler : public PyBaseProxyHandler {
2538
public:
26-
PyProxyHandler(PyObject *pyObject);
27-
PyObject *pyObject; // @TODO (Caleb Aikens) Consider putting this in a private slot
39+
PyProxyHandler(PyObject *pyObj) : PyBaseProxyHandler(pyObj) {};
2840

2941
/**
3042
* @brief [[OwnPropertyKeys]]
@@ -142,16 +154,29 @@ public:
142154
bool defineProperty(JSContext *cx, JS::HandleObject proxy,
143155
JS::HandleId id,
144156
JS::Handle<JS::PropertyDescriptor> desc,
145-
JS::ObjectOpResult &result) const override {};
157+
JS::ObjectOpResult &result) const override;
158+
};
159+
160+
/**
161+
* @brief This struct is the ProxyHandler for JS Proxy Objects pythonmonkey creates
162+
* to handle coercion from python lists to JS Array-like objects
163+
*/
164+
struct PyListProxyHandler : public PyBaseProxyHandler {
165+
public:
166+
PyListProxyHandler(PyObject *pyObj) : PyBaseProxyHandler(pyObj) {};
146167

147-
bool getPrototypeIfOrdinary(JSContext *cx, JS::HandleObject proxy,
148-
bool *isOrdinary,
149-
JS::MutableHandleObject protop) const override {};
168+
bool getOwnPropertyDescriptor(
169+
JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
170+
JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> desc
171+
) const override;
172+
173+
bool defineProperty(
174+
JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
175+
JS::Handle<JS::PropertyDescriptor> desc, JS::ObjectOpResult &result
176+
) const override;
150177

151-
bool preventExtensions(JSContext *cx, JS::HandleObject proxy,
152-
JS::ObjectOpResult &result) const override {};
153-
bool isExtensible(JSContext *cx, JS::HandleObject proxy,
154-
bool *extensible) const override {};
178+
bool ownPropertyKeys(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleIdVector props) const override;
179+
bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, JS::ObjectOpResult &result) const override;
155180
};
156181

157182
#endif

include/modules/pythonmonkey/pythonmonkey.hh

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,6 @@ static void cleanup();
4545
*/
4646
void memoizePyTypeAndGCThing(PyType *pyType, JS::Handle<JS::Value> GCThing);
4747

48-
/**
49-
* @brief This function checks if a given GCThing is memoized, and returns the related python object if so, or NULL otherwise
50-
*
51-
* @param GCThing - The GCThing to be checked
52-
* @return PyType* - Pointer to related python object wrapped in a PyType, or NULL if GCThing is not memoized
53-
*/
54-
PyType *checkJSMemo(JS::Handle<JS::Value> GCThing);
55-
5648
/**
5749
* @brief Callback function passed to JS_SetGCCallback to handle PythonMonkey shared memory
5850
*

python/pythonmonkey/pythonmonkey.pyi

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ stub file for type hints & documentations for the native module
66
import typing as _typing
77

88
# pylint: disable=redefined-builtin
9-
def eval(code: str) -> _typing.Any:
9+
def eval(code: str, /) -> _typing.Any:
1010
"""
1111
JavaScript evaluator in Python
1212
"""
@@ -17,13 +17,13 @@ def collect() -> None:
1717
"""
1818

1919
@_typing.overload
20-
def asUCS4(utf16_str: str) -> str:
20+
def asUCS4(utf16_str: str, /) -> str:
2121
"""
2222
Expects a python string in UTF16 encoding, and returns a new equivalent string in UCS4.
2323
Undefined behaviour if the string is not in UTF16.
2424
"""
2525
@_typing.overload
26-
def asUCS4(anything_else: _typing.Any) -> _typing.NoReturn: ...
26+
def asUCS4(anything_else: _typing.Any, /) -> _typing.NoReturn: ...
2727

2828
class bigint(int):
2929
"""
@@ -35,6 +35,12 @@ class SpiderMonkeyError(Exception):
3535
Representing a corresponding JS Error in Python
3636
"""
3737

38+
class JSObjectProxy(dict):
39+
"""
40+
JavaScript Object proxy dict
41+
"""
42+
def __init__(self) -> None: ...
43+
3844
null = _typing.Annotated[
3945
_typing.NewType("pythonmonkey.null", object),
4046
"Representing the JS null type in Python using a singleton object",

src/DictType.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
#include <jsfriendapi.h>
99
#include <jsapi.h>
10-
#include <js/Equality.h>
1110

1211
#include <Python.h>
1312

@@ -20,7 +19,7 @@ DictType::DictType() {
2019
DictType::DictType(PyObject *object) : PyType(object) {}
2120

2221
DictType::DictType(JSContext *cx, JS::Handle<JS::Value> jsObject) {
23-
JSObjectProxy *proxy = PyObject_New(JSObjectProxy, &JSObjectProxyType);
22+
JSObjectProxy *proxy = (JSObjectProxy *)PyObject_CallObject((PyObject *)&JSObjectProxyType, NULL);
2423
JS::RootedObject obj(cx);
2524
JS_ValueToObject(cx, jsObject, &obj);
2625
proxy->jsObject.set(obj);

0 commit comments

Comments
 (0)