comparison pydershell/pydershell.py @ 18:69e5523ebdc6

Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
author Atul Varma <varmaa@toolness.com>
date Mon, 07 Sep 2009 04:38:44 -0700
parents 1d62177c5c27
children 057260102960
comparison
equal deleted inserted replaced
17:1d62177c5c27 18:69e5523ebdc6
79 type(jsobject).__name__) 79 type(jsobject).__name__)
80 object.__setattr__(self, '_jsobject', jsobject) 80 object.__setattr__(self, '_jsobject', jsobject)
81 object.__setattr__(self, '_cx', cx) 81 object.__setattr__(self, '_cx', cx)
82 object.__setattr__(self, '_this', this) 82 object.__setattr__(self, '_this', this)
83 83
84 def __wrap_to_python(self, value): 84 @staticmethod
85 if isinstance(value, pydermonkey.Object): 85 def wrap(cx, jsvalue, this):
86 return SafeJsObjectWrapper(self._cx, value, self._jsobject) 86 if isinstance(jsvalue, pydermonkey.Function):
87 else: 87 return SafeJsFunctionWrapper(cx, jsvalue, this)
88 return value 88 elif isinstance(jsvalue, pydermonkey.Object):
89 89 return SafeJsObjectWrapper(cx, jsvalue, this)
90 def __wrap_to_js(self, value): 90 else:
91 # It's a primitive value.
92 return jsvalue
93
94 def _wrap_to_python(self, jsvalue):
95 return self.wrap(self._cx, jsvalue, self._jsobject)
96
97 def _wrap_to_js(self, value):
91 # TODO: Add support for wrapping non-primitive python objects. 98 # TODO: Add support for wrapping non-primitive python objects.
92 return value 99 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 100
107 def __eq__(self, other): 101 def __eq__(self, other):
108 if isinstance(other, SafeJsObjectWrapper): 102 if isinstance(other, SafeJsObjectWrapper):
109 return self._jsobject == other._jsobject 103 return self._jsobject == other._jsobject
110 else: 104 else:
122 def __setattr__(self, name, value): 116 def __setattr__(self, name, value):
123 cx = self._cx 117 cx = self._cx
124 jsobject = self._jsobject 118 jsobject = self._jsobject
125 119
126 cx.define_property(jsobject, name, 120 cx.define_property(jsobject, name,
127 self.__wrap_to_js(value)) 121 self._wrap_to_js(value))
128 122
129 def __getitem__(self, item): 123 def __getitem__(self, item):
130 return self.__getattr__(item) 124 return self.__getattr__(item)
131 125
132 def __getattr__(self, name): 126 def __getattr__(self, name):
133 cx = self._cx 127 cx = self._cx
134 jsobject = self._jsobject 128 jsobject = self._jsobject
135 129
136 return self.__wrap_to_python(cx.get_property(jsobject, name)) 130 return self._wrap_to_python(cx.get_property(jsobject, name))
137 131
138 def __contains__(self, item): 132 def __contains__(self, item):
139 cx = self._cx 133 cx = self._cx
140 jsobject = self._jsobject 134 jsobject = self._jsobject
141 135
146 jsobject = self._jsobject 140 jsobject = self._jsobject
147 141
148 properties = cx.enumerate(jsobject) 142 properties = cx.enumerate(jsobject)
149 for property in properties: 143 for property in properties:
150 yield property 144 yield property
145
146 class SafeJsFunctionWrapper(SafeJsObjectWrapper):
147 """
148 Securely wraps a JS function to behave like any normal Python object.
149 """
150
151 def __init__(self, cx, jsfunction, this):
152 if not isinstance(jsfunction, pydermonkey.Function):
153 raise TypeError("Cannot wrap '%s' object" %
154 type(jsobject).__name__)
155 SafeJsObjectWrapper.__init__(self, cx, jsfunction, this)
156
157 def __call__(self, *args):
158 cx = self._cx
159 jsobject = self._jsobject
160 this = self._this
161
162 obj = cx.call_function(this, jsobject,
163 self._wrap_to_js(args))
164 return self._wrap_to_python(obj)
151 165
152 def safejsfunc(cx, on_obj, name=None): 166 def safejsfunc(cx, on_obj, name=None):
153 """ 167 """
154 Exposes the decorated Python function on the given JS object. 168 Exposes the decorated Python function on the given JS object.
155 169
222 globalobj = cx.new_object() 236 globalobj = cx.new_object()
223 cx.init_standard_classes(globalobj) 237 cx.init_standard_classes(globalobj)
224 238
225 @safejsfunc(cx, globalobj) 239 @safejsfunc(cx, globalobj)
226 def bar(cx, this, args): 240 def bar(cx, this, args):
227 obj = SafeJsObjectWrapper(cx, args[0], this) 241 obj = SafeJsObjectWrapper.wrap(cx, args[0], this)
228 print obj.bar() 242 print obj.bar()
229 243
230 @safejsfunc(cx, globalobj) 244 @safejsfunc(cx, globalobj)
231 def foo(cx, this, args): 245 def foo(cx, this, args):
232 return cx.call_function(this, args[0], ()) 246 return cx.call_function(this, args[0], ())