Mercurial > scratch
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], ()) |