Mercurial > scratch
changeset 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 |
files | pydershell/pydershell.py |
diffstat | 1 files changed, 35 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/pydershell/pydershell.py Mon Sep 07 04:23:09 2009 -0700 +++ b/pydershell/pydershell.py Mon Sep 07 04:38:44 2009 -0700 @@ -81,29 +81,23 @@ object.__setattr__(self, '_cx', cx) object.__setattr__(self, '_this', this) - def __wrap_to_python(self, value): - if isinstance(value, pydermonkey.Object): - return SafeJsObjectWrapper(self._cx, value, self._jsobject) + @staticmethod + def wrap(cx, jsvalue, this): + if isinstance(jsvalue, pydermonkey.Function): + return SafeJsFunctionWrapper(cx, jsvalue, this) + elif isinstance(jsvalue, pydermonkey.Object): + return SafeJsObjectWrapper(cx, jsvalue, this) else: - return value + # It's a primitive value. + return jsvalue - def __wrap_to_js(self, value): + def _wrap_to_python(self, jsvalue): + return self.wrap(self._cx, jsvalue, self._jsobject) + + def _wrap_to_js(self, value): # TODO: Add support for wrapping non-primitive python objects. return value - def __call__(self, *args): - cx = self._cx - jsobject = self._jsobject - this = self._this - - if isinstance(jsobject, pydermonkey.Function): - obj = cx.call_function(this, jsobject, - self.__wrap_to_js(args)) - return self.__wrap_to_python(obj) - else: - raise TypeError("'%s' object is not callable" % - type(jsobject).__name__) - def __eq__(self, other): if isinstance(other, SafeJsObjectWrapper): return self._jsobject == other._jsobject @@ -124,7 +118,7 @@ jsobject = self._jsobject cx.define_property(jsobject, name, - self.__wrap_to_js(value)) + self._wrap_to_js(value)) def __getitem__(self, item): return self.__getattr__(item) @@ -133,7 +127,7 @@ cx = self._cx jsobject = self._jsobject - return self.__wrap_to_python(cx.get_property(jsobject, name)) + return self._wrap_to_python(cx.get_property(jsobject, name)) def __contains__(self, item): cx = self._cx @@ -149,6 +143,26 @@ for property in properties: yield property +class SafeJsFunctionWrapper(SafeJsObjectWrapper): + """ + Securely wraps a JS function to behave like any normal Python object. + """ + + def __init__(self, cx, jsfunction, this): + if not isinstance(jsfunction, pydermonkey.Function): + raise TypeError("Cannot wrap '%s' object" % + type(jsobject).__name__) + SafeJsObjectWrapper.__init__(self, cx, jsfunction, this) + + def __call__(self, *args): + cx = self._cx + jsobject = self._jsobject + this = self._this + + obj = cx.call_function(this, jsobject, + self._wrap_to_js(args)) + return self._wrap_to_python(obj) + def safejsfunc(cx, on_obj, name=None): """ Exposes the decorated Python function on the given JS object. @@ -224,7 +238,7 @@ @safejsfunc(cx, globalobj) def bar(cx, this, args): - obj = SafeJsObjectWrapper(cx, args[0], this) + obj = SafeJsObjectWrapper.wrap(cx, args[0], this) print obj.bar() @safejsfunc(cx, globalobj)