def descr__getattr__(self, space, name): h_res = support.emjs_prop_get_str(self.handle, name) if h_res == support.EMJS_UNDEFINED: raise OperationError(space.w_AttributeError, space.wrap(name)) w_res = _wrap_handle(space, h_res) # Turn functions into methods during attribute lookup. # XXX TODO: find a non-exception-driven check for this. try: func = space.interp_w(W_Function, w_res) except OperationError, e: if not e.match(space, space.w_TypeError): raise
def dispatch_callback(dataptr, h_args): id = rffi.cast(lltype.Signed, dataptr) callback = global_callback_map.get(id) if callback is None: raise RuntimeError("invalid callback id; was it garbage-collected?") space = callback.space # Unpack h_args as an extension of the default args from the callback. # If the callback wants the value of 'this', pass it as first argument. args_w, kw_w = callback.__args__.unpack() if kw_w: raise RuntimeError("callback function kw args not implemented yet") h_args_len = support.emjs_length(h_args) all_args_len = len(args_w) + h_args_len if callback.wants_this: all_args_len += 1 all_args_w = [None] * all_args_len i = 0 if callback.wants_this: h_this = support.emjs_prop_get_str(h_args, "this") w_this = _wrap_handle(space, h_this) all_args_w[0] = w_this i += 1 for w_arg in args_w: all_args_w[i] = w_arg i += 1 for j in xrange(h_args_len): w_arg = _wrap_handle(space, support.emjs_prop_get_int(h_args, j)) all_args_w[i] = w_arg i += 1 # Do the call, propagating return value or error as appropriate. try: w_res = space.call(callback.w_callback, space.newtuple(all_args_w)) except OperationError, pyerr: # XXX TODO: tunnel the exception through JS and back to Python? # XXX TODO: allow the callback to raise js.Error and reflect it # properly through to the javascript side. # w_jserror = getstate(space).w_jserror # if isinstance(pyerr, w_jserror): # with _unwrap_handle(pyerror.args[0]) as h_err: # support.emjs_set_error(h_err) # else: # h_msg = make_error_string() # h_data = make_error_pickle() # h_err = new(h_pyerror, [h_msg, h_data]) # support.emjs_set_error(h_err) # support.emjs_free(h_err) errmsg = pyerr.errorstr(space) h_errmsg = support.emjs_make_strn(errmsg, len(errmsg)) support.emjs_set_error(h_errmsg) support.emjs_free(h_errmsg) return support.EMJS_ERROR
def descr__getitem__(self, space, w_prop): if space.isinstance_w(w_prop, space.w_str): prop = space.str_w(w_prop) h_res = support.emjs_prop_get_str(self.handle, prop) elif space.isinstance_w(w_prop, space.w_int): prop = space.int_w(w_prop) h_res = support.emjs_prop_get_int(self.handle, prop) elif space.isinstance_w(w_prop, space.w_long): prop = space.int_w(w_prop) h_res = support.emjs_prop_get_int(self.handle, prop) else: with _unwrap_handle(space, w_prop) as h_prop: h_res = support.emjs_prop_get(self.handle, h_prop) return _wrap_handle(space, h_res)
def startup(self, space): # Hold a permanent handle to the globals object. self.h_globals = support.emjs_globals() _check_error(space, self.h_globals) # And a permanent object while we're at it. self.w_globals.handle = self.h_globals # Hold a permanent handle to the Array type constructor. self.h_array = support.emjs_prop_get_str(self.h_globals, "Array") _check_error(space, self.h_array) # Create a custom Error type for throwing errors from python callbacks. self.h_pyerror = support.emjs_eval(""" (function() { function PyError(message) { this.name = PyError; this.message = message || 'Python Error'; } PyError.prototype = new Error(); PyError.prototype.constructor = PyError; return PyError; })() """) _check_error(space, self.h_pyerror)