From d9592da6732f7cc8f2cba2fb30c01a6b8d457780 Mon Sep 17 00:00:00 2001 From: Roman Volosatovs Date: Wed, 12 Mar 2025 13:08:01 +0100 Subject: [PATCH] fix(p3): remove `body` accessors Currently, there are two ways to acquire a handle to the incoming request/response body handle: 1. Call `body` method on the request/response 2. Call `into-parts` static function on the request/response Assume pseudocode: ``` body := response.body() stream := body.stream() stream.read(buf) drop(stream) drop(body) // Forgetting this would cause a trap (_, body) := Response::into_parts(response) ``` There are quite a few issues in the example above. 1. It's very easy to make a mistake and cause a runtime trap, developers must very closely follow the WIT definition and read documentation to avoid a crash at runtime. 2. The host must do a lot of work and state tracking to e.g. ensure underlying body stream state synchronisation. If `body` method can be called at most once, that simplifes the task and potentially, the host could *move* the ownership of the body into the returned resource and *move* it back on `drop` of the body resource. Regardless of the approach and semantics, introducing multiple accessors for the `body` requires increased complexity in the host. To fix this, simply remove the `body` accessors. This way only a single way to acquire a body resource exists, which eliminates the possibility of misusing the interface by the application developer and simplifies implementation in the host. Signed-off-by: Roman Volosatovs --- wit-0.3.0-draft/types.wit | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/wit-0.3.0-draft/types.wit b/wit-0.3.0-draft/types.wit index 31eb62a..0a09233 100644 --- a/wit-0.3.0-draft/types.wit +++ b/wit-0.3.0-draft/types.wit @@ -354,13 +354,6 @@ interface types { /// component by e.g. `handler.handle`. headers: func() -> headers; - /// Get the body associated with the Request, if any. - /// - /// This body resource is a child: it must be dropped before the parent - /// `request` is dropped, or its ownership is transferred to another - /// component by e.g. `handler.handle`. - body: func() -> option; - /// Takes ownership of the `request` and returns the `headers` and `body`, /// if any. into-parts: static func(this: request) -> tuple>; @@ -437,13 +430,6 @@ interface types { /// component by e.g. `handler.handle`. headers: func() -> headers; - /// Get the body associated with the Response, if any. - /// - /// This body resource is a child: it must be dropped before the parent - /// `response` is dropped, or its ownership is transferred to another - /// component by e.g. `handler.handle`. - body: func() -> option; - /// Takes ownership of the `response` and returns the `headers` and `body`, /// if any. into-parts: static func(this: response) -> tuple>;