Exception creating string representation of javascript Object if constructor is undefined
See original GitHub issue🐛 Bug
I’ve been trying to prove out building a simple VueJS app with PyScript and running into strange errors of the form:
JsException(TypeError: Cannot read properties of undefined (reading 'name')) TypeError: Cannot read properties of undefined (reading 'name')
After much debugging, I see at least one of the errors is happening when pyodide attempts to create a string representation of a javascript object when the object has an undefined constructor. Using an object like this seems to be common in Vue (the ‘publicThis’ variable used for method binding is of this form).
To Reproduce
debug.html
<!DOCTYPE html>
<html>
<head>
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<body>
<script>
obj = Object();
obj.constructor = undefined;
</script>
<py-script src="./debug.py"></py-script>
<py-repl></py-repl>
</body>
</html>
debug.py
import pyodide
import js
try:
str(js.obj)
except Exception as err:
console.log(f"{err!r}", err)
javascript console
pyodide.asm.js:14 JsException(TypeError: Cannot read properties of undefined (reading 'name')) TypeError: Cannot read properties of undefined (reading 'name')
at hiwire_is_typedarray (pyodide.asm.js:14:227151)
at pyodide.asm.wasm:0xee398
at pyodide.asm.wasm:0xeea6e
at js2python (pyodide.asm.js:14:230955)
at pyodide.asm.wasm:0xefd61
at pyodide.asm.wasm:0x178583
at pyodide.asm.wasm:0x2005f9
at pyodide.asm.wasm:0x1f98b5
at pyodide.asm.wasm:0x1f97a0
at pyodide.asm.wasm:0x1f6ad9
Expected behavior
To produce a string representation with no exceptions thrown.
Environment
- Pyodide Version: 0.20.0
- Browser version: Brave 1.40.113 Chromium 103.0.5060.114 (macOS 12.4 Monterey)
- Any other relevant information:
Related Issue
Somewhat unrelated; the pyodide.create_proxy()
object does not have a javascript .bind()
method, and otherwise does not conform to the javascript function api that VueJS is expecting. I had to wrap my pyodide proxy objects in a javascript function to get it to work at all.
This may be fixed (https://github.com/pyodide/pyodide/pull/2769), although a bind that is a no-op would not provide any access to the bound javascript ‘this’ object if the python function needs access to that to perform its job (and I think that a Vue component method does need such access to function).
jsfn_wrap = js.Function("proxy_fn", """\
function wrapper() {
// wrap this in an Object to avoid pyodide string-ification bug
return proxy_fn.apply({this: this}, arguments);
}
return wrapper;
""")
def function_proxy(py_func):
proxy = pyodide.create_proxy(py_func)
jsfn = jsfn_wrap(proxy)
return jsfn
Additional context
Issue Analytics
- State:
- Created a year ago
- Comments:8 (4 by maintainers)
I believe the primary issue reported here is fixed on master:
I think this is the best we can do because
o.toString()
itself throws an error.It would be good to close this issue and create two new ones:
bind
andthis
and libraries that rely on them?