view docs/rendered/_sources/pymonkey.txt @ 130:4705522c7431

Added notes about weak-referencability to docs.
author Atul Varma <varmaa@toolness.com>
date Sun, 23 Aug 2009 17:57:04 -0700
parents d30576edf797
children 0c81cb18c935
line wrap: on
line source

:mod:`pymonkey` --- Access SpiderMonkey from Python
===================================================

.. module:: pymonkey
   :synopsis: Access SpiderMonkey from Python

.. testsetup:: *

   import pymonkey

This module offers a low-level interface to the `Mozilla SpiderMonkey
<https://developer.mozilla.org/en/SpiderMonkey>`_ JavaScript engine.

.. exception:: error

   This is the type of any SpiderMonkey-related errors thrown by this
   module.

.. data:: undefined

   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!

.. class:: Object

   This is the type of JavaScript objects. Such objects can only be
   created via Pymonkey calls like :meth:`Context.new_object()` or
   through the execution of JS code, but this type object can be used
   with Python's built-in :func:`isinstance()` to verify that an
   object is a JS object, like so:

     >>> obj = pymonkey.Runtime().new_context().new_object()
     >>> isinstance(obj, pymonkey.Object)
     True

   .. method:: get_runtime()

      Returns the :class:`Runtime` that the object belongs to.

.. class:: Function

   This is the type of JavaScript functions, which is a subtype of
   :class:`Object`.

.. class:: Context

   This is the type of JavaScript context objects. Contexts can only
   be created via a call to :meth:`Runtime.new_context()`, but this
   type object can be used with Python's built-in :func:`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.

   .. method:: get_runtime()

      Returns the :class:`Runtime` that the context belongs to.

   .. method:: new_object([private_obj])

      Creates a new :class:`Object` instance and returns
      it. ``private_obj`` is any Python object that is privately
      stored within the new JS object; it can be retrieved using
      :meth:`get_object_private()`.

   .. method:: new_function(func, name)

      Creates a new :class:`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 :class:`Context` that represents the
      JS context which is calling the function.

      The second argument is an :class:`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

   .. method:: define_property(object, name, value)

      Creates a new property on `object`, bypassing any JavaScript setters.

   .. method:: get_property(object, name)

      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 :data:`undefined`:

        >>> cx.get_property(obj, 'carrots')
        pymonkey.undefined

   .. method:: get_object_private(object)

      Returns the ``private_obj`` passed to :meth:`new_object()`
      when `object` was first created. If it doesn't exist, ``None``
      is returned.

      If `object` was created with :meth:`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.

   .. method:: clear_object_private(object)

      Clears the ``private_obj`` passed to :meth:`new_object()`
      when `object` was first created. If it doesn't exist, this
      function returns nothing.

      If `object` was created with :meth:`new_function()`, then this
      method effectively "unbinds" the Python callable wrapped by
      `object`. If `object` is later called, an exception will be
      raised.

   .. method:: evaluate_script(globalobj, code, filename, lineno)

      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

   .. method:: call_function(thisobj, func, args)

      Calls a JavaScript function.

      `thisobj` is an :class:`Object` that will be used as the value
      of ``this`` when the function executes, `func` is the
      :class:`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

   .. method:: init_standard_classes(object)

      Defines the standard JavaScript classes on the given
      :class:`Object`, such as ``Array``, ``eval``, ``undefined``, and
      so forth. For more information, see the documentation to
      `JS_InitStandardClasses()
      <https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JS_InitStandardClasses>`_,
      which this method wraps.

   .. method:: gc()

      Performs garbage collection on the context's JavaScript runtime.

   .. method:: set_operation_callback(func)

      Sets the operation callback for the context to the given Python
      callable. The callback can be triggered via
      :meth:`trigger_operation_callback()`.

      `func` takes one argument: the context that triggered it.

   .. method:: trigger_operation_callback()

      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
      :meth:`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.

.. class:: Runtime()

   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.

   .. method:: new_context()

      Creates a new Context object and returns it. Contexts are best
      conceptualized as threads of execution in a JS runtme; each one
      has a program counter, a current exception state, and so
      forth. JS objects may be freely accessed and changed by contexts
      that are associated with the same JS runtime as the objects.