object prototype chaining does not work correctly on proxied python objects
zollqir opened this issue · 2 comments
Describe your feature request here.
Proxied python objects currently do not have a proper prototype chain, and we are instead mimicking prototype chain behaviour by special-casing [[GetOwnPropertyDescriptor]] when the prop name is equal to a default prop name on the intended prototype.
For example, in:
import pythonmonkey as pm
l = [1, 2, 3]
pm.eval("(l) => l.pop()")(l)
l.pop
is accomplished by us intercepting prop lookup on l
, seeing that the prop name is "pop"
, and passing back our own implementation of pop
that is special-cased for python lists. This has some interesting consequences:
pm.eval("(l) => Object.getPrototypeOf(l) === Array.prototype")(l) # True
pm.eval("(l) => l.pop === Array.prototype.pop")(l) # False, should be True
pm.eval("(l) => l.pop === l.pop")(l) # False!!, should DEFINITELY be True
I propose that we define our own classes/prototypes for our proxied objects, and have those classes/prototypes inherit from the respective mimicked types, like so:
listObject = []
dictObject = []
bytesObject = b""
iterObject = iter(())
class Class:
pass
classObject = Class()
pm.eval("""
(listObject, dictObject, bytesObject, iterObject, classObject) => {
assert(Object.getPrototypeOf(listObject) === PyListProxy.prototype);
assert(Object.getPrototypeOf(dictObject) === PyDictProxy.prototype);
assert(Object.getPrototypeOf(bytesObject) === PyBytesProxy.prototype);
assert(Object.getPrototypeOf(iterObject) === PyIterProxy.prototype);
assert(Object.getPrototypeOf(classObject) === PyObjectProxy.prototype); // would be interesting if we could get python class
inheritance to be represented in the prototype chain with proxied Classes, though I don't think that's currently in scope, particularly since Python has true multiple inheritance
assert(Object.getPrototypeOf(PyListProxy.prototype) === Array.prototype);
assert(Object.getPrototypeOf(PyDictProxy.prototype) === Object.prototype);
assert(Object.getPrototypeOf(PyBytesProxy.prototype) === Uint8Array.prototype);
assert(Object.getPrototypeOf(PyIterProxy.prototype) === Object.prototype);
assert(Object.getPrototypeOf(PyObjectProxy.prototype) === Object.prototype);
}
""")(listObject, dictObject, bytesObject, iterObject, classObject)
Code example
No response
Q: Is this holding up BiFrost 2? If so, how? If not, we should pull this from the 1.0 Milestone
Some thoughts:
- it should be possible to write the majority of this in JS and decorate the prototypes from C++ and/or Python as-needed
- let's avoid adding more symbols to the global namespace, ctor funs can be in
python.classes
or something
@wesgarland it is not holding up Bifrost2 - it was moved to the > V1.0.1 release (aka after 1.0 Milestone)