`flx_args` is overwritten while parsing
Winand opened this issue · 4 comments
pscript generates broken code for functions like def partial2(func, *args, **keywords):
When trying to parse *args it overwrites arguments[0]:
func = arguments[0].flx_args[0]; /* overwrites here */
args = arguments[0].flx_args.slice(1); /* arguments[0].flx_args == undefined */
I am sorry, but I am having trouble understanding the problem. I don't see how fle_args[0]
is overwritten; it is only indexed, right?
I tried to work with the example in your PR:
from pscript import py2js, evaljs
def partial2(a1, a2, *args, **kwargs):
print(a1, a2)
print(args)
print(kwargs)
print('--')
def main():
partial2(3, 4, 5, 6, foo=3, bar=4)
js = py2js(partial2)
# print(js)
print(evaljs(js + py2js(main) + 'main(); partial2(3, 4, 5)'))
Which produces this, which seems fine:
3 4
[ 5, 6 ]
{ foo: 3, bar: 4 }
--
3 4
[ 5 ]
{}
--
null
Could you please try to adjust this code for it to cause the error on your end? That would hopefully make things more explicit :)
Ok, I created a file test.py
:
def partial2(a1, a2, *args, **kwargs):
print(a1, a2)
print(args)
print(kwargs)
print('--')
def main():
partial2(3, 4, 5, 6, foo=3, bar=4)
main()
partial2(3, 4, 5)
Then I compiled it to test.js with script2js
:
/* Do not edit, autogenerated by pscript */
var _pyfunc_op_error = function (etype, msg) { // nargs: 2
var e = new Error(etype + ': ' + msg);
e.name = etype
return e;
};
var _pyfunc_op_parse_kwargs = function (arg_names, arg_values, kwargs, strict) { // nargs: 3
for (var i=0; i<arg_values.length; i++) {
var name = arg_names[i];
if (kwargs[name] !== undefined) {
arg_values[i] = kwargs[name];
delete kwargs[name];
}
}
if (strict && Object.keys(kwargs).length > 0) {
throw _pyfunc_op_error('TypeError',
'Function ' + strict + ' does not accept **kwargs.');
}
return kwargs;
};
var main, partial2;
partial2 = function flx_partial2 (a1, a2) {
var args, kwargs, stub1_args;
kwargs = {};
if (arguments.length == 1 && typeof arguments[0] == 'object' && Object.keys(arguments[0]).toString() == 'flx_args,flx_kwargs') {
kwargs = _pyfunc_op_parse_kwargs([], [], arguments[0].flx_kwargs);
stub1_args = arguments[0].flx_args;
a1 = stub1_args[0];
a2 = stub1_args[1];
args = arguments[0].flx_args.slice(2);
} else {args = Array.prototype.slice.call(arguments, 2);}
console.log(a1 + " " + a2);
console.log(args);
console.log(kwargs);
console.log("--");
return null;
};
main = function flx_main () {
partial2({flx_args: [3, 4, 5, 6], flx_kwargs: {foo: 3, bar: 4}});
return null;
};
main();
partial2(3, 4, 5);
When running this script in Chrome 70 I get the following error:
How is it possible?
I couldn't believe it but when we assign a1 = stub1_args[0];
we assign 3 to arguments[0]
😞
Wow! This is madness ... but I can confirm it on both Chrome and Firefox (Windows 10). It looks like a1
is somehow bound to the same spot in memory as argumens[0]
, but that's not how variables are supposed to work, right? Is this some obscure result of the browser's JS optimization?
JS is full of surprises :(