Mercurial > pydertron
view docs.txt @ 35:6ddc83bb61f8 default tip
added another gc test
author | Atul Varma <avarma@mozilla.com> |
---|---|
date | Mon, 10 May 2010 21:01:58 -0700 |
parents | 0b00162939ae |
children |
line wrap: on
line source
========= Pydertron ========= Pydertron is an experimental high-level wrapper for `Pydermonkey`__ that provides convenient, secure object wrapping between JS and Python space. Note that Pydertron is just one example of a high-level interface between Python and JavaScript: it assumes, for instance, that the JS code it executes isn't trusted, which affects the nature of the inter-language interaction. Pydertron is currently hosted at http://hg.toolness.com/pydertron. Please feel free to send any questions or comments to atul@mozilla.com. The Basics ---------- 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. __ http://code.google.com/p/pydermonkey __ http://wiki.commonjs.org/wiki/CommonJS/Modules/SecurableModules __ http://wiki.commonjs.org/wiki/CommonJS 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)) __ http://interoperablejs.googlecode.com/svn/trunk/compliance/monkeys/ 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 aims is to make debugging JS code as much like debugging Python code as possible. Exceptions ---------- Any exceptions raised by wrapped Python functions need to be of type ``pydermonkey.ScriptError`` to be propagated into calling JavaScript code; if they're not, then for security purposes, the entire JavaScript call stack is unrolled. For example, here's a function that's bound to fail: >>> @jsexposed ... def fail(): ... o() >>> sandbox.root.fail = fail Now, even though the following JS code calls the function in a try-catch block, the JS code doesn't catch anything and its execution is simply halted: >>> sandbox.run_script("try { fail(); } catch (e) {}", ... stderr=sys.stdout) #doctest: +ELLIPSIS An internal error occurred. Traceback (most recent call last): ... NameError: global name 'o' is not defined -1 Note that a ``KeyboardInterrupt`` triggered while JS is executing will have similar effect.