RemoteCallResult (@NotNull RemoteCall call) { Object[] transformedArgs = transformArgs(call); Object result; if (call instanceof NewInstanceCall) { Class<?> targetClass = getTargetClass(call); Constructor<?> constructor = getConstructor(call, targetClass, transformedArgs); LOG.debug("Creating instance of " + targetClass); result = withSemantics(call, () -> invokeConstructor(constructor, transformedArgs)); } else { CallTarget callTarget = getCallTarget(call, transformedArgs); LOG.debug("Calling " + callTarget); Object instance; try { instance = findInstance(call, callTarget.clazz()); } catch (Exception e) { LOG.error("Unable to get instance for " + call); throw new RuntimeException("Unable to get instance for " + call, e); } if (call.getDispatcher() == OnDispatcher.EDT) { Object[] res = new Object[1]; ApplicationManager.getApplication().invokeAndWait(() -> { res[0] = withSemantics(call, () -> invokeMethod(callTarget, instance, transformedArgs)); }); result = res[0]; } else { // todo handle OnDispatcher: Default or IO result = withSemantics(call, () -> invokeMethod(callTarget, instance, transformedArgs)); } Method targetMethod = callTarget.targetMethod(); if (Collection.class.isAssignableFrom(targetMethod.getReturnType())) { Type returnType = targetMethod.getGenericReturnType(); if (returnType instanceof ParameterizedType) { Type[] typeArguments = ((ParameterizedType)returnType).getActualTypeArguments(); if (typeArguments.length == 1 && typeArguments[0] instanceof Class<?> componentType) { if (isPassByValue(componentType)) { return new RemoteCallResult(result); } } } } else if (targetMethod.getReturnType().isArray()) { if (isPassByValue(targetMethod.getReturnType().getComponentType())) { return new RemoteCallResult(result); } } } if (isPassByValue(result)) { // does not need a session, pass by value return new RemoteCallResult(result); } if (call.getSessionId() == NO_SESSION_ID) { int id = REF_SEQUENCE.getAndIncrement(); Ref ref = RefProducer.makeRef(id, result); adhocReferenceMap.put(id, new WeakReference<>(result)); if (result instanceof Collection<?>) { List<Ref> items = new ArrayList<>(((Collection<?>)result).size()); for (Object item : ((Collection<?>)result)) { items.add(putAdhocReference(item)); } return new RemoteCallResult(new RefList(id, result.getClass().getName(), items)); } if (result.getClass().isArray()) { Object[] array = (Object[])result; List<Ref> items = new ArrayList<>(array.length); for (Object item : array) { items.add(putAdhocReference(item)); } return new RemoteCallResult(new RefList(id, result.getClass().getName(), items)); } return new RemoteCallResult(ref); } else { Session session = sessions.get(call.getSessionId()); Ref ref = session.putReference(result); // also make variable available out ouf `driver.withContext { }` block as weak reference adhocReferenceMap.put(ref.id(), new WeakReference<>(result)); if (result instanceof Collection<?>) { List<Ref> items = new ArrayList<>(((Collection<?>)result).size()); for (Object item : ((Collection<?>)result)) { Ref child = session.putReference(item); adhocReferenceMap.put(child.id(), new WeakReference<>(item)); items.add(child); } return new RemoteCallResult(new RefList(ref.id(), result.getClass().getName(), items)); } if (result.getClass().isArray()) { int length = Array.getLength(result); List<Ref> items = new ArrayList<>(length); for (int i = 0; i < length; i++) { Object item = Array.get(result, i); Ref child = session.putReference(item); adhocReferenceMap.put(child.id(), new WeakReference<>(item)); items.add(child); } return new RemoteCallResult(new RefList(ref.id(), result.getClass().getName(), items)); } return new RemoteCallResult(ref); } }