comparison pydershell/pydershell.py @ 17:1d62177c5c27

Added a safe js object wrapper.
author Atul Varma <varmaa@toolness.com>
date Mon, 07 Sep 2009 04:23:09 -0700
parents a78570a423ea
children 69e5523ebdc6
comparison
equal deleted inserted replaced
16:a78570a423ea 17:1d62177c5c27
63 """ 63 """
64 64
65 def __init__(self): 65 def __init__(self):
66 BaseException.__init__(self) 66 BaseException.__init__(self)
67 self.exc_info = sys.exc_info() 67 self.exc_info = sys.exc_info()
68
69 class SafeJsObjectWrapper(object):
70 """
71 Securely wraps a JS object to behave like any normal Python object.
72 """
73
74 __slots__ = ['_jsobject', '_cx', '_this']
75
76 def __init__(self, cx, jsobject, this):
77 if not isinstance(jsobject, pydermonkey.Object):
78 raise TypeError("Cannot wrap '%s' object" %
79 type(jsobject).__name__)
80 object.__setattr__(self, '_jsobject', jsobject)
81 object.__setattr__(self, '_cx', cx)
82 object.__setattr__(self, '_this', this)
83
84 def __wrap_to_python(self, value):
85 if isinstance(value, pydermonkey.Object):
86 return SafeJsObjectWrapper(self._cx, value, self._jsobject)
87 else:
88 return value
89
90 def __wrap_to_js(self, value):
91 # TODO: Add support for wrapping non-primitive python objects.
92 return value
93
94 def __call__(self, *args):
95 cx = self._cx
96 jsobject = self._jsobject
97 this = self._this
98
99 if isinstance(jsobject, pydermonkey.Function):
100 obj = cx.call_function(this, jsobject,
101 self.__wrap_to_js(args))
102 return self.__wrap_to_python(obj)
103 else:
104 raise TypeError("'%s' object is not callable" %
105 type(jsobject).__name__)
106
107 def __eq__(self, other):
108 if isinstance(other, SafeJsObjectWrapper):
109 return self._jsobject == other._jsobject
110 else:
111 return False
112
113 def __str__(self):
114 return self.toString()
115
116 def __unicode__(self):
117 return self.toString()
118
119 def __setitem__(self, item, value):
120 self.__setattr__(item, value)
121
122 def __setattr__(self, name, value):
123 cx = self._cx
124 jsobject = self._jsobject
125
126 cx.define_property(jsobject, name,
127 self.__wrap_to_js(value))
128
129 def __getitem__(self, item):
130 return self.__getattr__(item)
131
132 def __getattr__(self, name):
133 cx = self._cx
134 jsobject = self._jsobject
135
136 return self.__wrap_to_python(cx.get_property(jsobject, name))
137
138 def __contains__(self, item):
139 cx = self._cx
140 jsobject = self._jsobject
141
142 return cx.has_property(jsobject, item)
143
144 def __iter__(self):
145 cx = self._cx
146 jsobject = self._jsobject
147
148 properties = cx.enumerate(jsobject)
149 for property in properties:
150 yield property
68 151
69 def safejsfunc(cx, on_obj, name=None): 152 def safejsfunc(cx, on_obj, name=None):
70 """ 153 """
71 Exposes the decorated Python function on the given JS object. 154 Exposes the decorated Python function on the given JS object.
72 155
138 cx = rt.new_context() 221 cx = rt.new_context()
139 globalobj = cx.new_object() 222 globalobj = cx.new_object()
140 cx.init_standard_classes(globalobj) 223 cx.init_standard_classes(globalobj)
141 224
142 @safejsfunc(cx, globalobj) 225 @safejsfunc(cx, globalobj)
226 def bar(cx, this, args):
227 obj = SafeJsObjectWrapper(cx, args[0], this)
228 print obj.bar()
229
230 @safejsfunc(cx, globalobj)
143 def foo(cx, this, args): 231 def foo(cx, this, args):
144 return cx.call_function(this, args[0], ()) 232 return cx.call_function(this, args[0], ())
145 233
146 @safejsfunc(cx, globalobj, 'print') 234 @safejsfunc(cx, globalobj, 'print')
147 def jsprint(cx, this, args): 235 def jsprint(cx, this, args):