From 71563e58652c9596dd75b0fc94cc0bec4fba41e5 Mon Sep 17 00:00:00 2001 From: Yi LIU Date: Thu, 12 Feb 2026 20:08:52 +0800 Subject: [PATCH 1/2] chore: add dev-dependencies for integration tests Add wit-bindgen-core, wit-bindgen-rust, wit-bindgen-go, and wit-parser as workspace dev-dependencies to support integration test files. --- Cargo.lock | 1 + Cargo.toml | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 6ec91bbb3..872efb243 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1502,6 +1502,7 @@ dependencies = [ "wit-bindgen-rust", "wit-bindgen-test", "wit-component", + "wit-parser", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 3eada73a2..a8f2f264e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -119,3 +119,9 @@ csharp = ['dep:wit-bindgen-csharp'] csharp-mono = ['csharp'] moonbit = ['dep:wit-bindgen-moonbit'] async = [] + +[dev-dependencies] +wit-bindgen-core = { workspace = true } +wit-bindgen-rust = { workspace = true } +wit-bindgen-go = { workspace = true } +wit-parser = { workspace = true } From a14fff488c3a67d4701add04d239a177c203e21d Mon Sep 17 00:00:00 2001 From: Yi LIU Date: Thu, 12 Feb 2026 20:06:50 +0800 Subject: [PATCH 2/2] fix(go): prevent GC finalizer on borrowed resource handles FromBorrowHandle for imported resources was incorrectly delegating to FromOwnHandle, which registers a GC finalizer via runtime.AddCleanup. This violates the Component Model specification: borrowed handles are not owned by the callee, so the callee must not drop them. When Go's garbage collector ran, it would drop borrowed handles through the finalizer, corrupting the host's resource table. Fix FromBorrowHandle to create a handle object directly without registering a GC finalizer, preserving the correct ownership semantics. --- Cargo.lock | 1 - Cargo.toml | 6 ------ crates/go/src/lib.rs | 3 ++- tests/runtime/resource-borrow/runner.go | 20 ++++++++++++++++++++ tests/runtime/resource-borrow/test.go | 21 +++++++++++++++++++++ 5 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 tests/runtime/resource-borrow/runner.go create mode 100644 tests/runtime/resource-borrow/test.go diff --git a/Cargo.lock b/Cargo.lock index 872efb243..6ec91bbb3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1502,7 +1502,6 @@ dependencies = [ "wit-bindgen-rust", "wit-bindgen-test", "wit-component", - "wit-parser", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index a8f2f264e..3eada73a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -119,9 +119,3 @@ csharp = ['dep:wit-bindgen-csharp'] csharp-mono = ['csharp'] moonbit = ['dep:wit-bindgen-moonbit'] async = [] - -[dev-dependencies] -wit-bindgen-core = { workspace = true } -wit-bindgen-rust = { workspace = true } -wit-bindgen-go = { workspace = true } -wit-parser = { workspace = true } diff --git a/crates/go/src/lib.rs b/crates/go/src/lib.rs index 2c61536d3..1c290bced 100644 --- a/crates/go/src/lib.rs +++ b/crates/go/src/lib.rs @@ -2589,7 +2589,8 @@ func {camel}FromOwnHandle(handleValue int32) *{camel} {{ }} func {camel}FromBorrowHandle(handleValue int32) *{camel} {{ - return {camel}FromOwnHandle(handleValue) + handle := wit_runtime.MakeHandle(handleValue) + return &{camel}{{handle}} }} "# ); diff --git a/tests/runtime/resource-borrow/runner.go b/tests/runtime/resource-borrow/runner.go new file mode 100644 index 000000000..af0fc9766 --- /dev/null +++ b/tests/runtime/resource-borrow/runner.go @@ -0,0 +1,20 @@ +package export_wit_world + +import ( + "fmt" + test "wit_component/test_resource_borrow_to_test" +) + +func Run() { + thing := test.MakeThing(42) + defer thing.Drop() + + result := test.Foo(thing) + assertEqual(result, uint32(42+1+2)) +} + +func assertEqual[T comparable](a T, b T) { + if a != b { + panic(fmt.Sprintf("%v not equal to %v", a, b)) + } +} diff --git a/tests/runtime/resource-borrow/test.go b/tests/runtime/resource-borrow/test.go new file mode 100644 index 000000000..d03986e50 --- /dev/null +++ b/tests/runtime/resource-borrow/test.go @@ -0,0 +1,21 @@ +package export_test_resource_borrow_to_test + +import ( + "runtime" +) + +type Thing struct { + pinner runtime.Pinner + handle int32 + val uint32 +} + +func (self *Thing) OnDrop() {} + +func MakeThing(v uint32) *Thing { + return &Thing{runtime.Pinner{}, 0, v + 1} +} + +func Foo(v *Thing) uint32 { + return v.val + 2 +}