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 __del__(self): if we_are_translated() or support and support.emjs_free: support.emjs_free(self.handle)