Links

pmuellr is Patrick Mueller

other pmuellr thangs: home page, twitter, flickr, github

Wednesday, April 22, 2009

nitro_pie

One of the things I wanted to start doing in the new job was to play with the JavaScriptCore framework. But it's a C language framework, and I don't typically associate C with "play". Good news is, if there's a C API, then there's a good chance you can talk to it from Python via the ctypes module.

I started down that route a little over a month ago, and it's gotten to the point where you can do some non-trivial things with it, so I got it all cleaned up, tagged, etc. It's called nitro_pie (Nitro is the new sexy name of JavaScriptCore), is available up at GitHub, with a downloadable .tar.gz available on the downloads page.

Here's an example of what you can do with it: nps.py; nps standing for nitro_pie shell. This Python program takes a JavaScript file name as a command-line argument, and runs it. It injects a new function, print(), into the JavaScript global environment, so you can actually see it do something. And of course that function is implemented in plain old Python. Here's "Hello World", which does what you would expect under nps.py:

print("Hello", " ", "World", "!")

Couldn't resist writing a simple benchmark to sum numbers from 1 to ?, and comparing Python and JavaScript:

---------------------------------------------------
Python
---------------------------------------------------
sum(100): 5050
...
sum(100000000): 5000000050000000

real    0m30.397s
user    0m29.799s
sys     0m0.126s

---------------------------------------------------
JavaScriptCore
---------------------------------------------------
sum(100.0): 5050.0
...
sum(100000000.0): 5.00000005e+15

real    0m7.685s
user    0m7.468s
sys     0m0.081s

The floats you see in the JavaScript version are because JavaScript only has floats. Well, kind of. One of the things I learned was that JavaScriptCore actually internally supports 31-bit (or so) integers as well (as tagged pointers). I suspect the conversion to float in this case happened when I converted to a string at the end.

Another interesting factoid I discovered, not having used eval() much in JavaScript:

eval("{a:1; b:2}") == 2

Can you see why? Here's a hint. The correct syntax for what I had intended was:

eval("({a:1, b:2})")

Usual caveats apply; early code, it uses ctypes so will occaisonally go all Bus error-y on ya if you're sloppy, not many diagnostics, etc. Only runs on Mac OS X, as that's the only place I know of that has a separate JavaScriptCore library. But good news is, you just need the nitro_pie.py file, because you already have JavaScriptCore and Python installed.

I also belatedly discovered that Apple already ships JavaScriptCore bindings for Python, which you can get by doing an import JavaScriptCore But that's only the raw bindings, which doesn't take too long to implement - making them usable is the real work here.

So now that I've got this beast, it's probably time to start playing with the ServerJS stuff again, especially since no one else was looking at JavaScriptCore.