11#![ allow( clippy:: missing_safety_doc) ]
22
33/// Wrapper for the Url crate and a URLSearchParams implementation that enables use from C++.
4+ use std:: cell:: RefCell ;
45use std:: marker:: PhantomData ;
56use std:: slice;
67use url:: { form_urlencoded, quirks, Url } ;
@@ -14,12 +15,15 @@ impl JSUrl {
1415 fn update_params ( & self ) {
1516 if let Some ( params) = unsafe { self . params . as_mut ( ) } {
1617 params. list = self . url . query_pairs ( ) . into_owned ( ) . collect ( ) ;
18+ if let UrlOrString :: Url ( _, ref serialized_query_cache) = params. url_or_str {
19+ * serialized_query_cache. borrow_mut ( ) = None ;
20+ }
1721 }
1822 }
1923}
2024
2125enum UrlOrString {
22- Url ( * mut JSUrl ) ,
26+ Url ( * mut JSUrl , RefCell < Option < String > > ) ,
2327 Str ( String ) ,
2428}
2529
@@ -36,7 +40,7 @@ impl JSUrlSearchParams {
3640 /// This is used in `params_to_string` to hand out a stable reference.
3741 fn update_url_or_str ( & mut self ) {
3842 match self . url_or_str {
39- UrlOrString :: Url ( url) => {
43+ UrlOrString :: Url ( url, ref serialized_query_cache ) => {
4044 let url = unsafe { url. as_mut ( ) . unwrap ( ) } ;
4145 if self . list . is_empty ( ) {
4246 url. url . set_query ( None ) ;
@@ -45,6 +49,7 @@ impl JSUrlSearchParams {
4549 pairs. clear ( ) ;
4650 pairs. extend_pairs ( self . list . iter ( ) ) ;
4751 }
52+ * serialized_query_cache. borrow_mut ( ) = None ;
4853 }
4954 UrlOrString :: Str ( _) => {
5055 let str = if self . list . is_empty ( ) {
@@ -222,7 +227,7 @@ pub unsafe extern "C" fn url_search_params(url: *mut JSUrl) -> *mut JSUrlSearchP
222227 if url. params . is_null ( ) {
223228 url. params = Box :: into_raw ( Box :: new ( JSUrlSearchParams {
224229 list : url. url . query_pairs ( ) . into_owned ( ) . collect ( ) ,
225- url_or_str : UrlOrString :: Url ( url) ,
230+ url_or_str : UrlOrString :: Url ( url, RefCell :: new ( None ) ) ,
226231 } ) ) ;
227232 }
228233 url. params
@@ -401,12 +406,19 @@ pub extern "C" fn params_sort(params: &mut JSUrlSearchParams) {
401406#[ no_mangle]
402407pub extern "C" fn params_to_string ( params : & JSUrlSearchParams ) -> SpecSlice < ' _ > {
403408 match & params. url_or_str {
404- UrlOrString :: Url ( url) => {
405- let url = unsafe { url. as_mut ( ) . unwrap ( ) } ;
406- match url. url . query ( ) {
407- Some ( query) => query. into ( ) ,
408- None => "" . into ( ) ,
409+ UrlOrString :: Url ( _, serialized_query_cache) => {
410+ if serialized_query_cache. borrow ( ) . is_none ( ) {
411+ let strict_string = form_urlencoded:: Serializer :: new ( String :: new ( ) )
412+ . extend_pairs ( & params. list )
413+ . finish ( ) ;
414+
415+ * serialized_query_cache. borrow_mut ( ) = Some ( strict_string) ;
409416 }
417+
418+ let cache = serialized_query_cache. borrow ( ) ;
419+ let str_ref = cache. as_ref ( ) . unwrap ( ) ;
420+
421+ SpecSlice :: new ( str_ref. as_ptr ( ) , str_ref. len ( ) )
410422 }
411423 UrlOrString :: Str ( str) => str. as_str ( ) . into ( ) ,
412424 }
0 commit comments