66//!
77//! This module includes utilities to send messages to the JS layer of the webview.
88
9- use serde:: Serialize ;
9+ use serde:: { Deserialize , Serialize } ;
1010use serde_json:: value:: RawValue ;
1111
12+ /// The `Callback` type is the return value of the `transformCallback` JavaScript function.
13+ #[ derive( Debug , Clone , Copy , Eq , PartialEq , Serialize , Deserialize ) ]
14+ pub struct CallbackFn ( pub usize ) ;
15+
1216/// The information about this is quite limited. On Chrome/Edge and Firefox, [the maximum string size is approximately 1 GB](https://stackoverflow.com/a/34958490).
1317///
1418/// [From MDN:](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length#description)
@@ -70,8 +74,8 @@ fn escape_json_parse(json: &RawValue) -> String {
7074/// ```
7175/// use tauri::api::ipc::format_callback;
7276/// // callback with a string argument
73- /// let cb = format_callback("callback-function-name" , &"the string response").unwrap();
74- /// assert!(cb.contains(r#"window["callback-function-name "]("the string response")"#));
77+ /// let cb = format_callback(12345 , &"the string response").unwrap();
78+ /// assert!(cb.contains(r#"window["12345 "]("the string response")"#));
7579/// ```
7680///
7781/// - With types implement [`serde::Serialize`]:
@@ -86,14 +90,14 @@ fn escape_json_parse(json: &RawValue) -> String {
8690/// }
8791///
8892/// let cb = format_callback(
89- /// "callback-function-name" ,
93+ /// 6789 ,
9094/// &MyResponse { value: String::from_utf8(vec![b'X'; 10_240]).unwrap()
9195/// }).expect("failed to serialize");
9296///
93- /// assert!(cb.contains(r#"window["callback-function-name "](JSON.parse('{"value":"XXXXXXXXX"#));
97+ /// assert!(cb.contains(r#"window["6789 "](JSON.parse('{"value":"XXXXXXXXX"#));
9498/// ```
95- pub fn format_callback < T : Serialize , S : AsRef < str > > (
96- function_name : S ,
99+ pub fn format_callback < T : Serialize > (
100+ function_name : CallbackFn ,
97101 arg : & T ,
98102) -> crate :: api:: Result < String > {
99103 macro_rules! format_callback {
@@ -106,7 +110,7 @@ pub fn format_callback<T: Serialize, S: AsRef<str>>(
106110 console.warn("[TAURI] Couldn't find callback id {fn} in window. This happens when the app is reloaded while Rust is running an asynchronous operation.")
107111 }}
108112 "# ,
109- fn = function_name. as_ref ( ) ,
113+ fn = function_name. 0 ,
110114 arg = $arg
111115 )
112116 }
@@ -169,8 +173,8 @@ pub fn format_callback<T: Serialize, S: AsRef<str>>(
169173// TODO: better example to explain
170174pub fn format_callback_result < T : Serialize , E : Serialize > (
171175 result : Result < T , E > ,
172- success_callback : impl AsRef < str > ,
173- error_callback : impl AsRef < str > ,
176+ success_callback : CallbackFn ,
177+ error_callback : CallbackFn ,
174178) -> crate :: api:: Result < String > {
175179 match result {
176180 Ok ( res) => format_callback ( success_callback, & res) ,
@@ -181,8 +185,15 @@ pub fn format_callback_result<T: Serialize, E: Serialize>(
181185#[ cfg( test) ]
182186mod test {
183187 use crate :: api:: ipc:: * ;
188+ use quickcheck:: { Arbitrary , Gen } ;
184189 use quickcheck_macros:: quickcheck;
185190
191+ impl Arbitrary for CallbackFn {
192+ fn arbitrary ( g : & mut Gen ) -> CallbackFn {
193+ CallbackFn ( usize:: arbitrary ( g) )
194+ }
195+ }
196+
186197 #[ test]
187198 fn test_escape_json_parse ( ) {
188199 let dangerous_json = RawValue :: from_string (
@@ -205,38 +216,33 @@ mod test {
205216
206217 // check abritrary strings in the format callback function
207218 #[ quickcheck]
208- fn qc_formating ( f : String , a : String ) -> bool {
209- // can not accept empty strings
210- if !f. is_empty ( ) && !a. is_empty ( ) {
211- // call format callback
212- let fc = format_callback ( f. clone ( ) , & a) . unwrap ( ) ;
213- fc. contains ( & format ! (
214- r#"window["{}"](JSON.parse('{}'))"# ,
215- f,
216- serde_json:: Value :: String ( a. clone( ) ) ,
217- ) ) || fc. contains ( & format ! (
218- r#"window["{}"]({})"# ,
219- f,
220- serde_json:: Value :: String ( a) ,
221- ) )
222- } else {
223- true
224- }
219+ fn qc_formating ( f : CallbackFn , a : String ) -> bool {
220+ // call format callback
221+ let fc = format_callback ( f, & a) . unwrap ( ) ;
222+ fc. contains ( & format ! (
223+ r#"window["{}"](JSON.parse('{}'))"# ,
224+ f. 0 ,
225+ serde_json:: Value :: String ( a. clone( ) ) ,
226+ ) ) || fc. contains ( & format ! (
227+ r#"window["{}"]({})"# ,
228+ f. 0 ,
229+ serde_json:: Value :: String ( a) ,
230+ ) )
225231 }
226232
227233 // check arbitrary strings in format_callback_result
228234 #[ quickcheck]
229- fn qc_format_res ( result : Result < String , String > , c : String , ec : String ) -> bool {
230- let resp = format_callback_result ( result . clone ( ) , c . clone ( ) , ec . clone ( ) )
231- . expect ( "failed to format callback result" ) ;
235+ fn qc_format_res ( result : Result < String , String > , c : CallbackFn , ec : CallbackFn ) -> bool {
236+ let resp =
237+ format_callback_result ( result . clone ( ) , c , ec ) . expect ( "failed to format callback result" ) ;
232238 let ( function, value) = match result {
233239 Ok ( v) => ( c, v) ,
234240 Err ( e) => ( ec, e) ,
235241 } ;
236242
237243 resp. contains ( & format ! (
238244 r#"window["{}"]({})"# ,
239- function,
245+ function. 0 ,
240246 serde_json:: Value :: String ( value) ,
241247 ) )
242248 }
0 commit comments