@@ -26,6 +26,8 @@ use objc2_web_kit::{WKURLSchemeHandler, WKURLSchemeTask};
2626
2727use crate :: { wkwebview:: WEBVIEW_STATE , RequestAsyncResponder , WryWebView } ;
2828
29+ const NO_COPY_DATA_THRESHOLD : usize = 128 * 1024 ;
30+
2931pub fn create ( name : & str ) -> & AnyClass {
3032 unsafe {
3133 // Include the address of WEBVIEW_STATE in the class name so that each dylib in the process
@@ -215,6 +217,7 @@ extern "C" fn start_task(
215217 check_task_is_valid ( & webview, task_key, task_uuid. clone ( ) ) ?;
216218
217219 let content = sent_response. body ( ) ;
220+ let content_len = content. len ( ) ;
218221 // default: application/octet-stream, but should be provided by the client
219222 let wanted_mime = sent_response. headers ( ) . get ( CONTENT_TYPE ) ;
220223 // default to 200
@@ -231,7 +234,7 @@ extern "C" fn start_task(
231234 }
232235 headers. insert (
233236 & * NSString :: from_str ( CONTENT_LENGTH . as_str ( ) ) ,
234- & * NSString :: from_str ( & content . len ( ) . to_string ( ) ) ,
237+ & * NSString :: from_str ( & content_len . to_string ( ) ) ,
235238 ) ;
236239
237240 // add headers
@@ -264,15 +267,24 @@ extern "C" fn start_task(
264267 } ) )
265268 . map_err ( |_e| crate :: Error :: CustomProtocolTaskInvalid ) ?;
266269
267- // Send data
268- let data = NSData :: alloc ( ) ;
269- // MIGRATE NOTE: we copied the content to the NSData because content will be freed
270- // when out of scope but NSData will also free the content when it's done and cause doube free.
271- let data = NSData :: initWithBytes_length (
272- data,
273- content. as_ptr ( ) as * mut c_void ,
274- content. len ( ) ,
275- ) ;
270+ let data = if content_len < NO_COPY_DATA_THRESHOLD {
271+ let data = NSData :: alloc ( ) ;
272+ // Keep small responses on the original copy path; no-copy deallocation costs more.
273+ NSData :: initWithBytes_length ( data, content. as_ptr ( ) as * mut c_void , content. len ( ) )
274+ } else {
275+ match sent_response. into_body ( ) {
276+ Cow :: Owned ( content) => NSData :: from_vec ( content) ,
277+ Cow :: Borrowed ( content) => {
278+ let data = NSData :: alloc ( ) ;
279+ // Copy borrowed responses because NSData cannot take ownership.
280+ NSData :: initWithBytes_length (
281+ data,
282+ content. as_ptr ( ) as * mut c_void ,
283+ content. len ( ) ,
284+ )
285+ }
286+ }
287+ } ;
276288
277289 // Check validity again
278290 check_webview_id_valid ( webview_id) ?;
0 commit comments