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

JS’s classes cannot be used correctly in python #170

Closed
zanxueyan opened this issue Sep 14, 2023 · 7 comments
Closed

JS’s classes cannot be used correctly in python #170

zanxueyan opened this issue Sep 14, 2023 · 7 comments

Comments

@zanxueyan
Copy link

Issue type

Bug

How did you install PythonMonkey?

Installed from pip

OS platform and distribution

Windows 11

Python version (python --version)

3.10

PythonMonkey version (pip show pythonmonkey)

0.2.1

Bug Description

When python calls js, it is not possible to modify the properties of a class through its methods.

consult:How to instantiate JS's classes in python?

Standalone code to reproduce the issue

//JS code
class Runoob {
  constructor(name, url) {
    this.name = name;
    this.url = url;
  }
  setname(name)
  {
      this.name = name;
      console.log("box");
      return this.name;
  }
}
//first Type:transmit the class
module.exports = Runoob

//secend Type: Create an instance pass an instance
pepole = new Runoob("ddd","www.baidu.com")

************
#python code


import pythonmonkey as pm

pep =pm.require("./pyreadjs")
#first Type Error:TypeError: class constructors must be invoked with 'new'

pep("ddd","www.baidu.com")
# but can't code like this:
#test = new pep("ddd","www.baidu.com")

print(pep.setname("test")) #can return OK
print(pep.name)     #NOT CHANGE

Relevant log output or backtrace

pythonmonkey.SpiderMonkeyError: TypeError: class constructors must be invoked with 'new'

Additional info if applicable

No response

What branch of PythonMonkey were you developing on? (If applicable)

No response

@wiwichips
Copy link
Collaborator

wiwichips commented Sep 14, 2023

Hi @zanxueyan , thank you so much for taking the time to play with PythonMonkey and submit this issue!

Since Python lacks a new keyword for instantiating objects, we had to add a new(class) function to the PythonMonkey API. Here's a small example:

import pythonmonkey as pm
jsDateClass = pm.Date
myDate = pm.new(jsDateClass)(0) # in js this would be: let myDate = new Date(0);

Here's the change you would need to make to get your code working

//JS code
class Runoob {
  constructor(name, url) {
    this.name = name;
    this.url = url;
  }
  setname(name)
  {
      this.name = name;
      console.log("box");
      return this.name;
  }
}
//first Type:transmit the class
module.exports = Runoob

//secend Type: Create an instance pass an instance
pepole = new Runoob("ddd","www.baidu.com")
#python code


import pythonmonkey as pm

Runoob =pm.require("./pyreadjs")
#first Type Error:TypeError: class constructors must be invoked with 'new'

pep = pm.new(Runoob)("ddd","www.baidu.com")
# but can't code like this:
#test = new pep("ddd","www.baidu.com")

print(pep.setname("test")) #can return OK
print(pep.name)     #NOT CHANGE

Running the python program results in the following output:

box
test
ddd

I changed a couple things in your python code here:

  1. Runoob = pm.require("./pyreadjs")
  • Get the JS class from pyreadjs.js
  1. pep = pm.new(Runoob)("ddd","www.baidu.com")
  • Instantiate a new Runoob and set a variable pep equal to it. I'm using the pm.new(Class)(args...) function to instantiate a new object

I'm sorry you had this experience, we'll try to improve the error message or improve the documentation so more people don't run into this in the future. Thank you!!!

@zanxueyan
Copy link
Author

Thanks a lot!

@zanxueyan
Copy link
Author

`import pythonmonkey as pm

Runoob = pm.require("./pyreadjs") # Get the JS class from pyreadjs.js

pep = pm.new(Runoob)("ddd", "www.baidu.com") # Instantiated object
print(pep.add(2, 3))
pep.setname("test")
print(pep.name) # You cannot get the value of the property directly in this way
##Whether you can support getting its value from an attribute???

print(pep.getname()) # You need to use the built-in function to get the value`

@wiwichips
Copy link
Collaborator

wiwichips commented Sep 28, 2023

Hi @zanxueyan Good catch!!! - you're right, something is wrong here...

import pythonmonkey as pm

Runoob = pm.require("./pyreadjs") # Get the JS class from pyreadjs.js

pep = pm.new(Runoob)("Will Pringle", "www.google.com") # Instantiated object
pep.setname("Joseph")

print(pep['name'])   # prints Will Pringle BUT SHOULD PRINT Joseph
print(pep.name)      # prints Will Pringle BUT SHOULD PRINT Joseph
print(pep.getname()) # prints Joseph

I'll file a bug report - thank you so much for finding and reporting this error!

@wiwichips
Copy link
Collaborator

wiwichips commented Sep 28, 2023

@zanxueyan check this out: #172 (comment)

seems to be another side effect of this bug - I'll notify you when we have it patched


import pythonmonkey as pm

pm.eval("""
class Human {
  constructor(name)
  {
    this.name = name;
  }

  setName(name)
  {
    this.name = name;
  }

  getName()
  {
    return this.name;
  }
}

""")

Human = pm.eval('Human')

person = pm.new(Human)('Will')

# setting it using setName
person.setName('Joe')

print(person.getName()) # prints "Joe"
print(person.name) # prints "Will" but should print "Joe"!!!
print(person['name']) # prints "Will" but should print "Joe"!!!

# now try setting it directly 
person.name = "Liang"

print(person.getName()) # prints "Joe"
print(person.name) # prints "Liang"!!!
print(person['name']) # prints "Liang"!!!

prints

Joe
Will
Will
Joe
Liang
Liang

@zanxueyan
Copy link
Author

@wiwichips Thank you very much! Are there any further optimization results at present? Looking forward to...

@wiwichips
Copy link
Collaborator

This should be solved in the next release of PythonMonkey - not sure when that is - but I'll make sure to notify you @ zanxueyan

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

No branches or pull requests

2 participants