Mercurial > scratch
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): |