Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

object prototype chaining does not work correctly on proxied python objects #399

Open
zollqir opened this issue Jul 30, 2024 · 2 comments
Open
Assignees
Milestone

Comments

@zollqir
Copy link
Collaborator

zollqir commented Jul 30, 2024

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

@wesgarland
Copy link
Collaborator

wesgarland commented Sep 4, 2024

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

@wiwichips
Copy link
Collaborator

@wesgarland it is not holding up Bifrost2 - it was moved to the > V1.0.1 release (aka after 1.0 Milestone)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In progress
Development

No branches or pull requests

4 participants