Merge branch '6.2.x'
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to run Details
Build and Deploy Snapshot / Verify (push) Blocked by required conditions Details
Deploy Docs / Dispatch docs deployment (push) Waiting to run Details

This commit is contained in:
Sébastien Deleuze 2025-04-01 09:53:42 +02:00
commit 5c93bb38c4
2 changed files with 33 additions and 5 deletions

View File

@ -19,6 +19,7 @@ package org.springframework.core;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import kotlin.Unit; import kotlin.Unit;
import kotlin.coroutines.CoroutineContext; import kotlin.coroutines.CoroutineContext;
@ -131,11 +132,7 @@ public abstract class CoroutinesUtils {
if (!(type.isMarkedNullable() && arg == null) && if (!(type.isMarkedNullable() && arg == null) &&
type.getClassifier() instanceof KClass<?> kClass && type.getClassifier() instanceof KClass<?> kClass &&
KotlinDetector.isInlineClass(JvmClassMappingKt.getJavaClass(kClass))) { KotlinDetector.isInlineClass(JvmClassMappingKt.getJavaClass(kClass))) {
KFunction<?> constructor = KClasses.getPrimaryConstructor(kClass); arg = box(kClass, arg);
if (!KCallablesJvm.isAccessible(constructor)) {
KCallablesJvm.setAccessible(constructor, true);
}
arg = constructor.call(arg);
} }
argMap.put(parameter, arg); argMap.put(parameter, arg);
} }
@ -161,6 +158,20 @@ public abstract class CoroutinesUtils {
return mono; return mono;
} }
private static Object box(KClass<?> kClass, @Nullable Object arg) {
KFunction<?> constructor = Objects.requireNonNull(KClasses.getPrimaryConstructor(kClass));
KType type = constructor.getParameters().get(0).getType();
if (!(type.isMarkedNullable() && arg == null) &&
type.getClassifier() instanceof KClass<?> parameterClass &&
KotlinDetector.isInlineClass(JvmClassMappingKt.getJavaClass(parameterClass))) {
arg = box(parameterClass, arg);
}
if (!KCallablesJvm.isAccessible(constructor)) {
KCallablesJvm.setAccessible(constructor, true);
}
return constructor.call(arg);
}
private static Flux<?> asFlux(Object flow) { private static Flux<?> asFlux(Object flow) {
return ReactorFlowKt.asFlux(((Flow<?>) flow)); return ReactorFlowKt.asFlux(((Flow<?>) flow));
} }

View File

@ -199,6 +199,15 @@ class CoroutinesUtilsTests {
} }
} }
@Test
fun invokeSuspendingFunctionWithNestedValueClassParameter() {
val method = CoroutinesUtilsTests::class.java.declaredMethods.first { it.name.startsWith("suspendingFunctionWithNestedValueClassParameter") }
val mono = CoroutinesUtils.invokeSuspendingFunction(method, this, "foo", null) as Mono
runBlocking {
Assertions.assertThat(mono.awaitSingle()).isEqualTo("foo")
}
}
@Test @Test
fun invokeSuspendingFunctionWithValueClassReturnValue() { fun invokeSuspendingFunctionWithValueClassReturnValue() {
val method = CoroutinesUtilsTests::class.java.declaredMethods.first { it.name.startsWith("suspendingFunctionWithValueClassReturnValue") } val method = CoroutinesUtilsTests::class.java.declaredMethods.first { it.name.startsWith("suspendingFunctionWithValueClassReturnValue") }
@ -328,6 +337,11 @@ class CoroutinesUtilsTests {
return value.value return value.value
} }
suspend fun suspendingFunctionWithNestedValueClassParameter(value: NestedValueClass): String {
delay(1)
return value.value.value
}
suspend fun suspendingFunctionWithValueClassReturnValue(): ValueClass { suspend fun suspendingFunctionWithValueClassReturnValue(): ValueClass {
delay(1) delay(1)
return ValueClass("foo") return ValueClass("foo")
@ -382,6 +396,9 @@ class CoroutinesUtilsTests {
@JvmInline @JvmInline
value class ValueClass(val value: String) value class ValueClass(val value: String)
@JvmInline
value class NestedValueClass(val value: ValueClass)
@JvmInline @JvmInline
value class ValueClassWithInit(val value: String) { value class ValueClassWithInit(val value: String) {
init { init {