view pydershell/pydershell.py @ 11:74f27983a350

Added more to pydershell.
author Atul Varma <varmaa@toolness.com>
date Sun, 06 Sep 2009 20:12:48 +0000
parents fb25af17bae6
children f024e41d0fb9
line wrap: on
line source

#! /usr/bin/env python

import sys
import time
import threading
import traceback
import pydermonkey

class InternalError(BaseException):
    def __init__(self):
        BaseException.__init__(self)
        self.exc_info = sys.exc_info()

rt = pydermonkey.Runtime()
cx = rt.new_context()
globalobj = cx.new_object()
cx.init_standard_classes(globalobj)

def safejsfunc(cx, on_obj, name=None):
    def make_wrapper(func):
        if name is None:
            func_name = func.__name__
        else:
            func_name = name
        def wrapper(func_cx, this, args):
            try:
                return func(func_cx, this, args)
            except pydermonkey.error:
                raise
            except Exception:
                raise InternalError()
        cx.define_property(
            on_obj,
            func_name, 
            cx.new_function(wrapper, func_name)
            )
        return func
    return make_wrapper

@safejsfunc(cx, globalobj)
def foo(cx, this, args):
    return cx.call_function(this, args[0], ())

@safejsfunc(cx, globalobj, 'print')
def jsprint(cx, this, args):
    if len(args) > 0:
        print args[0]

def opcb(cx):
    # Don't do anything; if a keyboard interrupt was triggered,
    # it'll get raised here automatically.
    pass

cx.set_operation_callback(opcb)

class State(object):
    def __init__(self):
        self.curr_exc = None
        self.curr_tb = None
        self.curr_js_stack = None

state = State()

def throwhook(cx):
    curr_exc = cx.get_pending_exception()
    if state.curr_exc != curr_exc:
        state.curr_exc = curr_exc
        state.py_stack = traceback.extract_stack()
        state.js_stack = cx.get_stack()

cx.set_throw_hook(throwhook)

def watchdog():
    while 1:
        time.sleep(0.25)
        cx.trigger_operation_callback()

thread = threading.Thread(target=watchdog)
thread.setDaemon(True)
thread.start()

filename = 'test.js'

def make_stack(js_stack):
    lines = []
    while js_stack:
        if js_stack['script']:
            script = js_stack['script']
            thing = dict(filename = script.filename,
                         lineno = js_stack['lineno'],
                         name = '<module>')
        elif js_stack['function'] and not js_stack['function'].is_python:
            func = js_stack['function']
            thing = dict(filename = func.filename,
                         lineno = js_stack['lineno'],
                         name = func.name)
        else:
            thing = None
        if thing:
            lines.insert(0, "  File \"%(filename)s\", line %(lineno)d, in %(name)s" % thing)
        js_stack = js_stack['caller']
    lines.insert(0, "Traceback (most recent call last):")
    return '\n'.join(lines)

try:
    cx.evaluate_script(globalobj, open(filename).read(), filename, 1)
except pydermonkey.error, e:
    print make_stack(state.js_stack)
    print e.args[1]
except InternalError, e:
    print "An internal error occurred."
    traceback.print_tb(e.exc_info[2])
    print e.exc_info[1]