MCPcopy Create free account
hub / github.com/Distributive-Network/PythonMonkey / getKey

Function getKey

src/JSObjectProxy.cc:83–143  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

81}
82
83static inline PyObject *getKey(JSObjectProxy *self, PyObject *key, JS::HandleId id, bool checkPropertyShadowsMethod) {
84 // look through the methods for dispatch
85 for (size_t index = 0;; index++) {
86 const char *methodName = JSObjectProxyType.tp_methods[index].ml_name;
87 if (methodName == NULL || !PyUnicode_Check(key)) {
88 JS::RootedValue value(GLOBAL_CX);
89 JS_GetPropertyById(GLOBAL_CX, *(self->jsObject), id, &value);
90 // if value is a JSFunction, bind `this` to self
91 /* (Caleb Aikens) its potentially problematic to bind it like this since if the function
92 * ever gets assigned to another object like so:
93 *
94 * jsObjA.func = jsObjB.func
95 * jsObjA.func() # `this` will be jsObjB not jsObjA
96 *
97 * It will be bound to the wrong object, however I can't find a better way to do this,
98 * and even pyodide works this way weirdly enough:
99 * https://github.com/pyodide/pyodide/blob/ee863a7f7907dfb6ee4948bde6908453c9d7ac43/src/core/jsproxy.c#L388
100 *
101 * if the user wants to get an unbound JS function to bind later, they will have to get it without accessing it through
102 * a JSObjectProxy (such as via pythonmonkey.eval or as the result of some other function)
103 */
104 if (value.isObject()) {
105 JS::RootedObject valueObject(GLOBAL_CX);
106 JS_ValueToObject(GLOBAL_CX, value, &valueObject);
107 js::ESClass cls;
108 JS::GetBuiltinClass(GLOBAL_CX, valueObject, &cls);
109 if (cls == js::ESClass::Function) {
110 JS::Rooted<JS::ValueArray<1>> args(GLOBAL_CX);
111 args[0].setObject(*((*(self->jsObject)).get()));
112 JS::RootedValue boundFunction(GLOBAL_CX);
113 if (!JS_CallFunctionName(GLOBAL_CX, valueObject, "bind", args, &boundFunction)) {
114 PyErr_Format(PyExc_SystemError, "%s JSAPI call failed", JSObjectProxyType.tp_name);
115 return NULL;
116 }
117 value.set(boundFunction);
118 }
119 }
120 else if (value.isUndefined() && PyUnicode_Check(key)) {
121 if (strcmp("__class__", PyUnicode_AsUTF8(key)) == 0) {
122 return PyObject_GenericGetAttr((PyObject *)self, key);
123 }
124 }
125
126 return pyTypeFactory(GLOBAL_CX, value);
127 }
128 else {
129 if (strcmp(methodName, PyUnicode_AsUTF8(key)) == 0) {
130 if (checkPropertyShadowsMethod) {
131 // just make sure no property is shadowing a method by name
132 JS::RootedValue value(GLOBAL_CX);
133 JS_GetPropertyById(GLOBAL_CX, *(self->jsObject), id, &value);
134 if (!value.isUndefined()) {
135 return pyTypeFactory(GLOBAL_CX, value);
136 }
137 }
138
139 return PyObject_GenericGetAttr((PyObject *)self, key);
140 }

Calls 3

pyTypeFactoryFunction · 0.85
getMethod · 0.80
setMethod · 0.65

Tested by

no test coverage detected