Wednesday, July 22, 2015

Rusthon and WebWorkers


Rusthon is the fork of PythonJS that I currently maintain and use on all my personal and work projects. It has an improved JavaScript transpiler, with a powerful syntax that mixes Python and Golang. Recently I added special syntax for timed processing and webworkers, see these posts: [1], [2]

WebWorkers

The WebWorker standard is many years old, but often web developers do not have time to break apart their code in order to use it. Code inside a webworker has no access to the DOM, and passing objects back and forth requires packing them into a message protocol. You also need to worry about loading your shared JavaScript with importScripts, or have some logic to create a URL Blob at runtime, and splitting off the worker code into its own file. In other words, refactoring your JavaScript to leverage webworkers, can be a big pain in the ass.

Rusthon has simple syntax inspired by Golang for using webworkers, see the wiki here. The transpiler and runtime take care of all the details of passing messages, reconstructing objects, splitting apart your code, and generating a URL blob at runtime. Example source code.

transpiler input

This example passes instances of SharedClass back and forth from webworker to the main thread. Python3 style function annotations are used to type the input arguments and return type, this allows the transpiler to inject code to restore the objects __proto__ class|prototype property, this is required when you intend to call methods on objects that cross from webworker to main, or main to webworker.

#backend:javascript
from runtime import *

def show(txt):
 document.getElementById('CONTAINER').appendChild(
  document.createTextNode(txt + '\n')
 )

class SharedClass:
 def __init__(self, x,y,z):
  self.x = x
  self.y = y
  self.z = z

 def foobar(self):
  return self.x + self.y + self.z


with webworker:
 def somefunction() -> SharedClass:
  s = SharedClass(10,20,30)
  return s

 class MyWorker:
  def send(self, obj:SharedClass ) -> SharedClass:
   print obj
   print obj.foobar()
   obj.x = 10
   return obj

  def somemethod(self) -> SharedClass:
   s = SharedClass(100,200,300)
   return s



def main():
 global WORKER
 show('spawn worker...')
 WORKER = spawn( MyWorker() )

 show('creating SharedClass')
 a = SharedClass(1,2,3)
 print(a)
 show(a.foobar())

 show('sending data to worker')
 WORKER <- a

 show('getting data from worker')
 b = <- WORKER
 show(b.foobar())

 c = <- somefunction()
 show(c.foobar())

 d = <- WORKER.somemethod()
 show(d.foobar())

javascript output - webworker

note below: somefunction.returns = "SharedClass"; is the result of this input from above def somefunction() -> SharedClass: that sets the return type of the function. The WebWorker runtime manager checks the returns property of functions it calls, and sets the __proto__ of the result in the main thread.

var somefunction = function()
{
 var s;
 s =  new SharedClass(10, 20, 30);
 return s;
}
somefunction.returns = "SharedClass";

var MyWorker = function(){}

MyWorker.prototype.send = function(obj)
{
 var obj;
 obj.__proto__ = SharedClass.prototype;
 console.log(obj);
 console.log(obj.foobar());
 obj.x = 10;
 return obj;
}
MyWorker.prototype.send.returns = "SharedClass";

MyWorker.prototype.somemethod = function()
{
 var s;
 s =  new SharedClass(100, 200, 300);
 return s;
}
MyWorker.prototype.somemethod.returns = "SharedClass";

javascript output - main

var show = function(txt)
{
 document.getElementById("CONTAINER").appendChild(document.createTextNode((txt + "\n")));
}

var SharedClass = function(x, y, z)
{
 this.__init__(x, y, z);
}

SharedClass.prototype.__init__ = function(x, y, z)
{
 this.x = x;
 this.y = y;
 this.z = z;
}

SharedClass.prototype.foobar = function()
{
 return ((this.x + this.y) + this.z);
}

var main = function()
{
 var a,c,b,d;
 show("spawn worker...");
 WORKER = __workerpool__.spawn({new:"MyWorker", args:[]});
 show("creating SharedClass");
 a =  new SharedClass(1, 2, 3);
 console.log(a);
 show(a.foobar());
 show("sending data to worker");
 __workerpool__.send({message:a,id:WORKER})
 show("getting data from worker");
  __workerpool__.recv( WORKER, function (b) {
  show(b.foobar());
   __workerpool__.call( "somefunction", [],  function (c) {
   show(c.foobar());
    __workerpool__.callmeth( WORKER, "somemethod", [],  function (d) {
    show(d.foobar());
   });
  });
 });
}

Tuesday, May 12, 2015

Rapydscript Kicks Ass


Rapydscript by Alexander Tsepkov is a Python to JavaScript translator that really kicks ass. It is stable, the transpiler can be run fully client side, produces very fast JavaScript, and is well maintained by Alex. Rapydscript syntax is very similar to PythonJS, and both can be used together in the same markdown file compiled by Rusthon.

Rapydscript has the right mix of Pythonic-style and features to make it inter-operate well with JavaScript. Alex made all the right choices on what parts of Python to throw away, and adapting the syntax to the requirements imposed by generating fast JavaScript. Check out this example for how to use Rapydscript in Rusthon.