Support 'setTimeout' and 'setInterval'
Currently I get this:
python -c 'import js2py; js2py.eval_js("setTimeout(function() {}, 1 );")'
[....]
js2py.base.PyJsException: ReferenceError: setTimeout is not defined
.. now how hard can implementing the event loop be? ;)
Anyhow, if this is implemented, with browserify one could use for example promise-a-plus to get a working Promise implementation.
You can implement in plain JavaScript. Hold on a moment I will write it now...
Okay, here it is:
function __get_event_env__() {
pyimport time;
var id = 0;
var sh = [];
function add_event(func, args, interval, id) {
var ev = [func, args, time.time()+interval/1000., id];
sh.push(ev);
}
function clear_event(id) {
var to_del = false;
for (var i=0; i<sh.length; i++) {
if (sh[i][3] === +id) {
to_del = i;
break;
}
}
if (to_del !== false) {
sh.splice(to_del, 1);
}
}
function exec_one() {
var t = time.time();
for (var i=0; i<sh.length; i++) {
if (sh[i][2] <= t) {
try {
sh[i][0].apply(Object(this), sh[i][1]);
} catch (e) {
// todo what should we do in case of errors?
}
clear_event(sh[i][3]);
break
}
}
}
function setTimeout(func, interval) {
var args = Array.prototype.slice.call(arguments, 2);
var my_id = ++id;
add_event(func, args, interval, my_id);
return my_id // todo return a full timeout object
}
function setInterval(func, interval) {
var args = Array.prototype.slice.call(arguments, 2);
var my_id = ++id;
function wrap() {
try {
func.apply(Object(my_id), args);
} finally {
add_event(wrap, [], interval, my_id)
}
}
add_event(wrap, [], interval, my_id);
return my_id // todo return a full timeout object
}
function event_loop() {
while (true) {
if (sh.length===0) {
break
}
exec_one();
time.sleep(0.001);
}
}
function clearInterval(timeoutObj) {
clear_event(timeoutObj);
}
var clearTimeout = clearInterval;
return [setTimeout, clearTimeout, setInterval, clearInterval, event_loop]
}
__event_env__ = __get_event_env__();
var setTimeout = __event_env__[0];
var clearTimeout = __event_env__[1];
var setInterval = __event_env__[2];
var clearInterval = __event_env__[3];
var __event_loop__ = __event_env__[4];
It works but I did not test it properly yet, remember to call __event_loop__ at the end of your program. I still have to implement a proper Timeout object to make it consistent with specs.
Well that was fast ;)
I faced some difficulties combining this with the webapp2 framework, where the handler functions are synchronous, and send the response to the client once the function returns, but adding the __event_loop__() call at the end of the handler seemed to work.
I have a feeling that this would make the server non-thread-safe, but as I am continuing this exercise mainly out of academic interest now, I don't think that is a huge problem ;)
I put the current version of the template project on Github if someone else wants to dabble with it in the future too: https://github.com/amv/gae-js2py-es2015-example
@amv I verified this is not thread-safe as you suspected.
@PiotrDabkowski in order for me to be able to use the tool, which I would love, I will need to figure out how to/if we can make it thread-safe.