This module offers a low-level interface to the Mozilla SpiderMonkey JavaScript engine.
This is the singleton that represents the JavaScript value undefined, as Python has no equivalent representation (JavaScript’s null is mapped to Python’s None object). For instance:
>>> cx = pymonkey.Runtime().new_context()
>>> cx.evaluate_script(cx.new_object(), '', '<string>', 1)
pymonkey.undefined
This object also has a “falsy” value:
>>> if not pymonkey.undefined:
... print "See, it's falsy!"
See, it's falsy!
This is the type of JavaScript objects. Such objects can only be created via Pymonkey calls like Context.new_object() or through the execution of JS code, but this type object can be used with Python’s built-in isinstance() to verify that an object is a JS object, like so:
>>> obj = pymonkey.Runtime().new_context().new_object()
>>> isinstance(obj, pymonkey.Object)
True
Note that Object and all its subclasses are identity-preserving when passed between Python-land and JS-land. For instance:
>>> cx = pymonkey.Runtime().new_context()
>>> obj1 = cx.new_object()
>>> obj2 = cx.evaluate_script(obj1, 'this', '<string>', 1)
>>> obj1 is obj2
True
This is the type of JavaScript functions, which is a subtype of Object.
This is the type of compiled JavaScript scripts; it’s actually a subtype of Object, though when exposed to JS code it doesn’t provide access to any special data or functionality.
Script instances have a read-only buffer interface that exposes their bytecode. This can be accessed by passing an instance to Python’s built-in buffer() function.
This is the type of JavaScript context objects. Contexts can only be created via a call to Runtime.new_context(), but this type object can be used with Python’s built-in isinstance() to verify that an object is a context, like so:
>>> cx = pymonkey.Runtime().new_context()
>>> isinstance(cx, pymonkey.Context)
True
JS contexts are weak-referencable.
Returns a dictionary containing information about the context’s current stack.
The dictionary contains the following string keys:
key | value |
---|---|
script | Script of the frame. This may be None if the frame isn’t a scripted frame, or if it’s not possible to expose the script to Python for some reason. |
lineno | Line number of the frame, if the frame is scripted. |
pc | Program counter of the frame; this is an index into the bytecode of the frame’s script, if the frame is scripted. |
function | The Function in which the frame is executing, if any. |
caller | Dictionary containing information about the stack frame of the caller of this frame. If this frame has no caller, this value is None. |
If the context isn’t currently executing any code (i.e., the stack is empty), this method returns None.
Creates a new Function instance that wraps the given Python callable. In JS-land, the function will have the given name.
When the function is executed from JavaScript, func will be passed three positional arguments.
The first argument is a Context that represents the JS context which is calling the function.
The second argument is an Object that represents the value of this for the duration of the call.
The third argument is a tuple containing the arguments passed to the function.
For instance:
>>> def add(cx, this, args):
... return args[0] + args[1]
>>> cx = pymonkey.Runtime().new_context()
>>> obj = cx.new_object()
>>> cx.define_property(obj, 'add', cx.new_function(add, 'add'))
>>> cx.evaluate_script(obj, 'add(1, 1);', '<string>', 1)
2
Finds the specified property on object and returns its value, possibly invoking a JavaScript getter.
Example:
>>> cx = pymonkey.Runtime().new_context()
>>> obj = cx.new_object()
>>> cx.define_property(obj, 'beets', 'i like beets.')
>>> cx.get_property(obj, 'beets')
u'i like beets.'
Note also that calling this function on undefined properties yields undefined:
>>> cx.get_property(obj, 'carrots')
pymonkey.undefined
Returns the private_obj passed to new_object() when object was first created. If it doesn’t exist, None is returned.
If object was created with new_function(), then this method returns the Python callable wrapped by object.
This functionality is useful if you want to securely represent Python objects in JS-land.
Clears the private_obj passed to new_object() when object was first created. If it doesn’t exist, this function returns nothing.
If object was created with new_function(), then this method effectively “unbinds” the Python callable wrapped by object. If object is later called, an exception will be raised.
Evaluates the text code using globalobj as the global object/scope.
It’s assumed that code is coming from the file named by filename; the first line of code is assumed to be line number lineno of filename. This metadata is very useful for debugging stack traces, exceptions, and so forth.
For example:
>>> cx = pymonkey.Runtime().new_context()
>>> obj = cx.new_object()
>>> cx.init_standard_classes(obj)
>>> cx.evaluate_script(obj, '5 * Math', '<string>', 1)
nan
Compiles the given string of code and returns a Script instance that can be executed via execute_script().
filename and lineno are used just as in evaluate_script().
Executes the code in the given Script object, using globalobj as the global object/scope, and returns the result.
For example:
>>> cx = pymonkey.Runtime().new_context()
>>> obj = cx.new_object()
>>> cx.init_standard_classes(obj)
>>> script = cx.compile_script('5 * Math', '<string>', 1)
>>> cx.execute_script(obj, script)
nan
Calls a JavaScript function.
thisobj is an Object that will be used as the value of this when the function executes, func is the Function to execute, and args is a tuple of arguments to pass to the function.
For instance:
>>> cx = pymonkey.Runtime().new_context()
>>> obj = cx.new_object()
>>> cx.init_standard_classes(obj)
>>> Math = cx.get_property(obj, 'Math')
>>> floor = cx.get_property(Math, 'floor')
>>> cx.call_function(Math, floor, (5.3,))
5
Sets the operation callback for the context to the given Python callable. The callback can be triggered via trigger_operation_callback().
func takes one argument: the context that triggered it.
Triggers the context’s operation callback. If no callback has yet been set, this function does nothing.
This function is one of the few thread-safe functions available to a JS runtime, and together with set_operation_callback() can be used to abort the execution of long-running code.
For instance, we first create an operation callback to stop long-running code by throwing an exception:
>>> import time, threading
>>> cx = pymonkey.Runtime().new_context()
>>> def stop_running_code(cx):
... raise Exception('JS took too long to execute.')
>>> cx.set_operation_callback(stop_running_code)
Then we create a watchdog thread to trigger the operation callback once a long amount of time has passed:
>>> def watchdog_thread():
... time.sleep(0.1) # An eternity to a computer!
... cx.trigger_operation_callback()
>>> thread = threading.Thread(target=watchdog_thread)
>>> thread.start()
Now, when we execute code that takes too long to run, it gets aborted:
>>> try:
... cx.evaluate_script(cx.new_object(), 'while (1) {}',
... '<string>', 1)
... except pymonkey.error, e:
... print cx.get_object_private(e.args[0])
JS took too long to execute.
Creates a new JavaScript runtime. JS objects created by the runtime may only interact with other JS objects of the same runtime.
With few exceptions, objects belonging to a runtime can currently only be used in the same thread that the runtime was created in. This may be changed in the future, since SpiderMonkey itself has support for thread safety.
JS runtimes are weak-referencable.