Pydertron is a high-level wrapper for Pydermonkey that provides convenient, secure object wrapping between JS and Python space.
The JsSandbox class encapsulates a JavaScript runtime, context, global object, and a simple SecurableModule implementation that complies with the CommonJS standard. It also provides a high-level bridge between Python and JavaScript so that you don't need to deal with any of the low-level details of the Pydermonkey API.
For instance, here we'll create a JsSandbox whose module root points to the monkeys SecurableModule compliance test over HTTP:
>>> url = ("http://interoperablejs.googlecode.com/svn/trunk/"
... "compliance/monkeys/")
>>> sandbox = JsSandbox(HttpFileSystem(url))
This compliance test requires a global sys object that contains one method, print(), that takes two arguments. First, we'll create the print() function and prepare it for exposure to JS code:
>>> @jsexposed ... def jsprint(message, label): ... print message, label
Note the use of the @jsexposed decorator: all this does is set the function's __jsexposed__ attribute to True. This is done for security purposes: only Python callables satisfying this criteria will be exposed to JavaScript code, to ensure that untrusted JS can't accidentally gain access to privileged Python functionality.
Creating a JS object can be done like this:
>>> system = sandbox.new_object()
We can now access and set properties on this object via either item or attribute lookup, just like in JavaScript. Because print is a reserved word in Python, though, we'll use item lookup to set the property here:
>>> system['print'] = jsprint
Now we tell the sandbox that we want the sys object to be a global:
>>> sandbox.set_globals(sys = system)
And finally, we execute the compliance test by running a one-line script that imports the 'program' module, like so:
>>> sandbox.run_script("require('program');")
PASS monkeys permitted pass
DONE info
0
Note the 0 in the last line: this is the return value of sandbox.run_script(), which returns 0 on success, and -1 if an exception was raised. For instance, the output of bad code looks like this:
>>> sandbox.run_script("(function foo() { bar(); })();",
... stderr=sys.stdout)
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "<string>", line 1, in foo
ReferenceError: bar is not defined
-1
Note that the traceback displayed is actually referring to JavaScript code: one of Pydertron's helpful conveniences is that it makes debugging JS code as much like debugging Python code as possible.