MAINT: Minor cleanup of pyproxy (#1136)

* Minor cleanup of pyproxy

* Fix `isPyProxy` to handle undefined or null argument correctly

* Remove _pyproxy_enumerate

* Remove stray semicolon

* Forgot to _getPtr in apply

* Forgot to "return Reflect.get"

* Cleanup a bit

* Update test to reflect changes to behavior of pyproxy_dir

* Try again to get test dir right

Co-authored-by: Jan Max Meyer <jmm@phorward.de>
This commit is contained in:
Hood Chatham 2021-01-17 11:11:48 -08:00 committed by GitHub
parent 83a1d7b328
commit cb3590b6c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 70 additions and 68 deletions

View File

@ -143,7 +143,7 @@ EM_JS_REF(PyObject*, __js2python, (JsRef id), {
} else if (value === false) {
return __js2python_false();
} else if (Module.PyProxy.isPyProxy(value)) {
return __js2python_pyproxy(Module.PyProxy.getPtr(value));
return __js2python_pyproxy(Module.PyProxy._getPtr(value));
} else if (value['byteLength'] !== undefined) {
return __js2python_memoryview(id);
} else {

View File

@ -119,12 +119,6 @@ _pyproxy_ownKeys(PyObject* pyobj)
return iddir;
}
JsRef
_pyproxy_enumerate(PyObject* pyobj)
{
return _pyproxy_ownKeys(pyobj);
}
JsRef
_pyproxy_apply(PyObject* pyobj, JsRef idargs)
{
@ -169,7 +163,8 @@ EM_JS_REF(JsRef, pyproxy_new, (PyObject * ptrobj), {
let target = function(){};
target['$$'] = { ptr : ptrobj, type : 'PyProxy' };
let proxy = new Proxy(target, Module.PyProxy);
Object.assign(target, Module.PyProxyPublicMethods);
let proxy = new Proxy(target, Module.PyProxyHandlers);
Module.PyProxies[ptrobj] = proxy;
return Module.hiwire.new_value(proxy);
@ -178,58 +173,66 @@ EM_JS_REF(JsRef, pyproxy_new, (PyObject * ptrobj), {
EM_JS(int, pyproxy_init, (), {
// clang-format off
Module.PyProxies = {};
function _getPtr(jsobj) {
let ptr = jsobj['$$']['ptr'];
if (ptr === null) {
throw new Error("Object has already been destroyed");
}
return ptr;
}
// Static methods
Module.PyProxy = {
getPtr: function(jsobj) {
let ptr = jsobj['$$']['ptr'];
if (ptr === null) {
throw new Error("Object has already been destroyed");
}
return ptr;
},
_getPtr,
isPyProxy: function(jsobj) {
return jsobj && jsobj['$$'] !== undefined && jsobj['$$']['type'] === 'PyProxy';
},
addExtraKeys: function(result) {
result.push('toString');
result.push('prototype');
result.push('arguments');
result.push('caller');
};
Module.PyProxyPublicMethods = {
toString : function() {
let ptrobj = _getPtr(this);
let jsref_repr = __pyproxy_repr(ptrobj);
let repr = Module.hiwire.get_value(jsref_repr);
Module.hiwire.decref(jsref_repr);
return repr;
},
destroy : function() {
let ptrobj = _getPtr(this);
__pyproxy_destroy(ptrobj);
this['$$']['ptr'] = null;
},
apply : function(jsthis, jsargs) {
let ptrobj = _getPtr(this);
let idargs = Module.hiwire.new_value(jsargs);
let idresult = __pyproxy_apply(ptrobj, idargs);
let jsresult = Module.hiwire.get_value(idresult);
Module.hiwire.decref(idresult);
Module.hiwire.decref(idargs);
return jsresult;
},
};
let ignoredTargetFields = ["name", "length"];
// See explanation of which methods should be defined here and what they do here:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
Module.PyProxyHandlers = {
isExtensible: function() { return true },
has: function (jsobj, jskey) {
let ptrobj = this.getPtr(jsobj);
if(Reflect.has(jsobj, jskey) && !ignoredTargetFields.includes(jskey)){
return true;
}
let ptrobj = _getPtr(jsobj);
let idkey = Module.hiwire.new_value(jskey);
let result = __pyproxy_has(ptrobj, idkey) !== 0;
Module.hiwire.decref(idkey);
return result;
},
get: function (jsobj, jskey) {
let ptrobj = this.getPtr(jsobj);
if (jskey === 'toString') {
return function() {
let jsref_repr = __pyproxy_repr(ptrobj);
let repr = Module.hiwire.get_value(jsref_repr);
Module.hiwire.decref(jsref_repr);
return repr;
}
} else if (jskey === '$$') {
return jsobj['$$'];
} else if (jskey === 'destroy') {
// See bug #1049
return function() {
__pyproxy_destroy(ptrobj);
jsobj['$$']['ptr'] = null;
}
} else if (jskey === 'apply') {
return function(jsthis, jsargs) {
let idargs = Module.hiwire.new_value(jsargs);
let idresult = __pyproxy_apply(ptrobj, idargs);
let jsresult = Module.hiwire.get_value(idresult);
Module.hiwire.decref(idresult);
Module.hiwire.decref(idargs);
return jsresult;
};
if(Reflect.has(jsobj, jskey) && !ignoredTargetFields.includes(jskey)){
return Reflect.get(jsobj, jskey);
}
let ptrobj = _getPtr(jsobj);
let idkey = Module.hiwire.new_value(jskey);
let idresult = __pyproxy_get(ptrobj, idkey);
let jsresult = Module.hiwire.get_value(idresult);
@ -238,7 +241,10 @@ EM_JS(int, pyproxy_init, (), {
return jsresult;
},
set: function (jsobj, jskey, jsval) {
let ptrobj = this.getPtr(jsobj);
if(Reflect.has(jsobj, jskey) && !ignoredTargetFields.includes(jskey)){
throw new Error(`Cannot set read only field ${jskey}`);
}
let ptrobj = _getPtr(jsobj);
let idkey = Module.hiwire.new_value(jskey);
let idval = Module.hiwire.new_value(jsval);
let idresult = __pyproxy_set(ptrobj, idkey, idval);
@ -249,7 +255,10 @@ EM_JS(int, pyproxy_init, (), {
return jsresult;
},
deleteProperty: function (jsobj, jskey) {
let ptrobj = this.getPtr(jsobj);
if(Reflect.has(jsobj, jskey) && !ignoredTargetFields.includes(jskey)){
throw new Error(`Cannot delete read only field ${jskey}`);
}
let ptrobj = _getPtr(jsobj);
let idkey = Module.hiwire.new_value(jskey);
let idresult = __pyproxy_deleteProperty(ptrobj, idkey);
let jsresult = Module.hiwire.get_value(idresult);
@ -258,29 +267,21 @@ EM_JS(int, pyproxy_init, (), {
return jsresult;
},
ownKeys: function (jsobj) {
let ptrobj = this.getPtr(jsobj);
let result = new Set(Reflect.ownKeys(jsobj));
for(let key of ignoredTargetFields){
result.delete(key);
}
let ptrobj = _getPtr(jsobj);
let idresult = __pyproxy_ownKeys(ptrobj);
let jsresult = Module.hiwire.get_value(idresult);
Module.hiwire.decref(idresult);
this.addExtraKeys(jsresult);
return jsresult;
},
enumerate: function (jsobj) {
let ptrobj = this.getPtr(jsobj);
let idresult = __pyproxy_enumerate(ptrobj);
let jsresult = Module.hiwire.get_value(idresult);
Module.hiwire.decref(idresult);
this.addExtraKeys(jsresult);
return jsresult;
for(let key of jsresult){
result.add(key);
}
return Array.from(result);
},
apply: function (jsobj, jsthis, jsargs) {
let ptrobj = this.getPtr(jsobj);
let idargs = Module.hiwire.new_value(jsargs);
let idresult = __pyproxy_apply(ptrobj, idargs);
let jsresult = Module.hiwire.get_value(idresult);
Module.hiwire.decref(idresult);
Module.hiwire.decref(idargs);
return jsresult;
return jsobj.apply(jsthis, jsargs);
},
};

View File

@ -52,8 +52,9 @@ def test_pyproxy(selenium):
"get_value",
"toString",
"prototype",
"arguments",
"caller",
"apply",
"destroy",
"$$",
]
)
assert selenium.run("hasattr(f, 'baz')")