Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1633,23 +1633,34 @@ extension JNISwift2JavaGenerator {
// Global ref all indirect returns
for outParameter in nativeFunctionSignature.result.outParameters {
printer.print(
"let \(outParameter.name) = environment.interface.NewGlobalRef(environment, \(outParameter.name))"
"nonisolated(unsafe) let \(outParameter.name) = environment.interface.NewGlobalRef(environment, \(outParameter.name))"
)
globalRefs.append(outParameter.name)
}

// We also need to global ref any objects passed in
for parameter in nativeFunctionSignature.parameters.flatMap(\.parameters) where !parameter.type.isPrimitive {
printer.print("let \(parameter.name) = environment.interface.NewGlobalRef(environment, \(parameter.name))")
printer.print("nonisolated(unsafe) let \(parameter.name) = environment.interface.NewGlobalRef(environment, \(parameter.name))")
globalRefs.append(parameter.name)
}

printer.print(
"""
let globalFuture = environment.interface.NewGlobalRef(environment, result_future)
nonisolated(unsafe) let globalFuture = environment.interface.NewGlobalRef(environment, result_future)
"""
)

if let selfParameter = nativeFunctionSignature.selfParameter {
for parameter in selfParameter.parameters {
printer.print("nonisolated(unsafe) let \(parameter.name)Sendable$ = \(parameter.name)$")
}
}
if let selfTypeParameter = nativeFunctionSignature.selfTypeParameter {
for parameter in selfTypeParameter.parameters {
printer.print("nonisolated(unsafe) let \(parameter.name)Sendable$ = \(parameter.name)$")
}
}

func printDo(printer: inout CodePrinter) {
// Make sure try/await are printed when necessary and avoid duplicate, or wrong-order, keywords (which would cause warnings)
let placeholderWithoutTry =
Expand Down Expand Up @@ -1692,6 +1703,16 @@ extension JNISwift2JavaGenerator {
}

func printTaskBody(printer: inout CodePrinter) {
if let selfParameter = nativeFunctionSignature.selfParameter {
for parameter in selfParameter.parameters {
printer.print("let \(parameter.name)$ = \(parameter.name)Sendable$")
}
}
if let selfTypeParameter = nativeFunctionSignature.selfTypeParameter {
for parameter in selfTypeParameter.parameters {
printer.print("let \(parameter.name)$ = \(parameter.name)Sendable$")
}
}
printer.printBraceBlock("defer") { printer in
// Defer might on any thread, so we need to attach environment.
printer.print("let deferEnvironment = try! JavaVirtualMachine.shared().environment()")
Expand Down Expand Up @@ -1722,8 +1743,8 @@ extension JNISwift2JavaGenerator {
printer.printHashIfBlock("swift(>=6.2)") { printer in
printer.printBraceBlock("if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)") { printer in
printer.printBraceBlock("task = Task.immediate") { printer in
// Immediate runs on the caller thread, so we don't need to attach the environment again.
printer.print("var environment = environment!") // this is to ensure we always use the same environment name, even though we are rebinding it.
// Even immediate tasks are a sending closure in Swift 6.2+, so reattach instead of capturing the caller's environment directly.
printer.print("var environment = try! JavaVirtualMachine.shared().environment()")
Comment thread
iDevid marked this conversation as resolved.
printTaskBody(printer: &printer)
}
}
Expand Down
20 changes: 10 additions & 10 deletions Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ struct JNIAsyncTests {
"""
@_cdecl("Java_com_example_swift_SwiftModule__00024asyncVoid__Ljava_util_concurrent_CompletableFuture_2")
public func Java_com_example_swift_SwiftModule__00024asyncVoid__Ljava_util_concurrent_CompletableFuture_2(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, result_future: jobject?) {
let globalFuture = environment.interface.NewGlobalRef(environment, result_future)
nonisolated(unsafe) let globalFuture = environment.interface.NewGlobalRef(environment, result_future)
var task: Task<Void, Never>? = nil
#if swift(>=6.2)
if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) {
task = Task.immediate {
var environment = environment!
var environment = try! JavaVirtualMachine.shared().environment()
defer {
let deferEnvironment = try! JavaVirtualMachine.shared().environment()
deferEnvironment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)
Expand Down Expand Up @@ -137,12 +137,12 @@ struct JNIAsyncTests {
"""
@_cdecl("Java_com_example_swift_SwiftModule__00024async__Ljava_util_concurrent_CompletableFuture_2")
public func Java_com_example_swift_SwiftModule__00024async__Ljava_util_concurrent_CompletableFuture_2(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, result_future: jobject?) {
let globalFuture = environment.interface.NewGlobalRef(environment, result_future)
nonisolated(unsafe) let globalFuture = environment.interface.NewGlobalRef(environment, result_future)
var task: Task<Void, Never>? = nil
#if swift(>=6.2)
if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) {
task = Task.immediate {
var environment = environment!
var environment = try! JavaVirtualMachine.shared().environment()
defer {
let deferEnvironment = try! JavaVirtualMachine.shared().environment()
deferEnvironment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)
Expand Down Expand Up @@ -227,12 +227,12 @@ struct JNIAsyncTests {
"""
@_cdecl("Java_com_example_swift_SwiftModule__00024async__JLjava_util_concurrent_CompletableFuture_2")
public func Java_com_example_swift_SwiftModule__00024async__JLjava_util_concurrent_CompletableFuture_2(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, i: jlong, result_future: jobject?) {
let globalFuture = environment.interface.NewGlobalRef(environment, result_future)
nonisolated(unsafe) let globalFuture = environment.interface.NewGlobalRef(environment, result_future)
var task: Task<Void, Never>? = nil
#if swift(>=6.2)
if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) {
task = Task.immediate {
var environment = environment!
var environment = try! JavaVirtualMachine.shared().environment()
defer {
let deferEnvironment = try! JavaVirtualMachine.shared().environment()
deferEnvironment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)
Expand Down Expand Up @@ -320,12 +320,12 @@ struct JNIAsyncTests {
guard let c$ else {
fatalError("c memory address was null in call to \\(#function)!")
}
let globalFuture = environment.interface.NewGlobalRef(environment, result_future)
nonisolated(unsafe) let globalFuture = environment.interface.NewGlobalRef(environment, result_future)
var task: Task<Void, Never>? = nil
#if swift(>=6.2)
if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) {
task = Task.immediate {
var environment = environment!
var environment = try! JavaVirtualMachine.shared().environment()
defer {
let deferEnvironment = try! JavaVirtualMachine.shared().environment()
deferEnvironment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)
Expand Down Expand Up @@ -403,8 +403,8 @@ struct JNIAsyncTests {
"""
@_cdecl("Java_com_example_swift_SwiftModule__00024async__Ljava_lang_String_2Ljava_util_concurrent_CompletableFuture_2")
public func Java_com_example_swift_SwiftModule__00024async__Ljava_lang_String_2Ljava_util_concurrent_CompletableFuture_2(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, s: jstring?, result_future: jobject?) {
let s = environment.interface.NewGlobalRef(environment, s)
let globalFuture = environment.interface.NewGlobalRef(environment, result_future)
nonisolated(unsafe) let s = environment.interface.NewGlobalRef(environment, s)
nonisolated(unsafe) let globalFuture = environment.interface.NewGlobalRef(environment, result_future)
...
defer {
let deferEnvironment = try! JavaVirtualMachine.shared().environment()
Expand Down
Loading