@@ -277,6 +277,9 @@ impl FunctionBindgen<'_> {
277277 /// let ret;
278278 /// ```
279279 ///
280+ /// This function returns as a first tuple parameter a list of
281+ /// variables that should be created via let statements beforehand.
282+ ///
280283 /// # Arguments
281284 ///
282285 /// * `amt` - number of results
@@ -287,35 +290,37 @@ impl FunctionBindgen<'_> {
287290 amt : usize ,
288291 results : & mut Vec < String > ,
289292 is_async : bool ,
290- ) -> String {
293+ ) -> ( String , String ) {
291294 let mut s = String :: new ( ) ;
295+ let mut vars_init = String :: new ( ) ;
292296 match amt {
293297 0 => {
294298 // Async functions with no returns still return async code,
295299 // which will be used as the initial callback result going into the async driver
296300 if is_async {
297- uwrite ! ( s, "let ret = " )
298- } else {
299- uwrite ! ( s, "let ret;" )
301+ uwrite ! ( s, "ret = " )
300302 }
303+ uwriteln ! ( vars_init, "let ret;" ) ;
301304 }
302305 1 => {
303- uwrite ! ( s, "let ret = " ) ;
306+ uwrite ! ( s, "ret = " ) ;
304307 results. push ( "ret" . to_string ( ) ) ;
308+ uwriteln ! ( vars_init, "let ret;" ) ;
305309 }
306310 n => {
307- uwrite ! ( s, "var [" ) ;
311+ uwrite ! ( s, "[" ) ;
308312 for i in 0 ..n {
309313 if i > 0 {
310314 uwrite ! ( s, ", " ) ;
311315 }
312- uwrite ! ( s, "ret{}" , i ) ;
316+ uwrite ! ( s, "ret{i}" ) ;
313317 results. push ( format ! ( "ret{i}" ) ) ;
318+ uwriteln ! ( vars_init, "let ret;" ) ;
314319 }
315320 uwrite ! ( s, "] = " ) ;
316321 }
317322 }
318- s
323+ ( vars_init , s )
319324 }
320325
321326 fn bitcast ( & mut self , cast : & Bitcast , op : & str ) -> String {
@@ -1482,20 +1487,44 @@ impl Bindgen for FunctionBindgen<'_> {
14821487 // Output result binding preamble (e.g. 'var ret =', 'var [ ret0, ret1] = exports...() ')
14831488 // along with the code to perofrm the call
14841489 let sig_results_length = sig. results . len ( ) ;
1485- let s = self . generate_result_assignment_lhs ( sig_results_length, results, is_async) ;
1486-
1487- let ( call_prefix, call_wrapper) = if self . requires_async_porcelain | self . is_async {
1488- ( "await " , Intrinsic :: WithGlobalCurrentTaskMetaFnAsync . name ( ) )
1489- } else {
1490- ( "" , Intrinsic :: WithGlobalCurrentTaskMetaFn . name ( ) )
1491- } ;
1490+ let ( vars_init, assignment_lhs) =
1491+ self . generate_result_assignment_lhs ( sig_results_length, results, is_async) ;
1492+
1493+ let ( call_prefix, call_wrapper, call_err_cleanup) =
1494+ if self . requires_async_porcelain | self . is_async {
1495+ (
1496+ "await " ,
1497+ Intrinsic :: WithGlobalCurrentTaskMetaFnAsync . name ( ) ,
1498+ r#"
1499+ task.reject(err);
1500+ task.exit();
1501+ return task.completionPromise();
1502+ "# ,
1503+ )
1504+ } else {
1505+ (
1506+ "" ,
1507+ Intrinsic :: WithGlobalCurrentTaskMetaFn . name ( ) ,
1508+ r#"
1509+ task.reject(err);
1510+ task.exit();
1511+ throw err;
1512+ "# ,
1513+ )
1514+ } ;
14921515 uwriteln ! (
14931516 self . src,
1494- r#"{s} {call_prefix} {call_wrapper}({{
1495- taskID: task.id(),
1496- componentIdx: task.componentIdx(),
1497- fn: () => {callee}({args}),
1498- }});
1517+ r#"
1518+ {vars_init}
1519+ try {{
1520+ {assignment_lhs} {call_prefix} {call_wrapper}({{
1521+ taskID: task.id(),
1522+ componentIdx: task.componentIdx(),
1523+ fn: () => {callee}({args}),
1524+ }});
1525+ }} catch (err) {{
1526+ {call_err_cleanup}
1527+ }}
14991528 "# ,
15001529 callee = self . callee,
15011530 args = operands. join( ", " ) ,
@@ -1644,30 +1673,57 @@ impl Bindgen for FunctionBindgen<'_> {
16441673 }
16451674
16461675 // Build the JS expression that calls the callee
1647- let ( call_prefix, call_wrapper) = if is_async || self . requires_async_porcelain {
1648- ( "await " , Intrinsic :: WithGlobalCurrentTaskMetaFnAsync . name ( ) )
1649- } else {
1650- ( "" , Intrinsic :: WithGlobalCurrentTaskMetaFn . name ( ) )
1651- } ;
1676+ let ( call_prefix, call_wrapper, call_err_cleanup) =
1677+ if is_async || self . requires_async_porcelain {
1678+ (
1679+ "await " ,
1680+ Intrinsic :: WithGlobalCurrentTaskMetaFnAsync . name ( ) ,
1681+ r#"
1682+ task.reject(err);
1683+ task.exit();
1684+ return task.completionPromise();
1685+ "# ,
1686+ )
1687+ } else {
1688+ (
1689+ "" ,
1690+ Intrinsic :: WithGlobalCurrentTaskMetaFn . name ( ) ,
1691+ r#"
1692+ task.reject(err);
1693+ task.exit();
1694+ throw err;
1695+ "# ,
1696+ )
1697+ } ;
16521698 let call = format ! (
16531699 r#"{call_prefix} {call_wrapper}({{
1654- componentIdx: task.componentIdx(),
1655- taskID: task.id(),
1656- fn: () => {callee_fn_js}({callee_args_js})
1657- }})
1700+ componentIdx: task.componentIdx(),
1701+ taskID: task.id(),
1702+ fn: () => {callee_fn_js}({callee_args_js}),
1703+ }})
16581704 "# ,
16591705 ) ;
16601706
16611707 match self . err {
16621708 // If configured to do *no* error handling at all or throw
16631709 // error objects directly, we can simply perform the call
16641710 ErrHandling :: None | ErrHandling :: ThrowResultErr => {
1665- let s = self . generate_result_assignment_lhs (
1711+ let ( vars_init , assignment_lhs ) = self . generate_result_assignment_lhs (
16661712 fn_wasm_result_count,
16671713 results,
16681714 is_async,
16691715 ) ;
1670- uwriteln ! ( self . src, "{s}{call};" ) ;
1716+ uwriteln ! (
1717+ self . src,
1718+ r#"
1719+ {vars_init}
1720+ try {{
1721+ {assignment_lhs}{call};
1722+ }} catch (err) {{
1723+ {call_err_cleanup}
1724+ }}
1725+ "#
1726+ ) ;
16711727 }
16721728 // If configured to force all thrown errors into result objects,
16731729 // then we add a try/catch around the call
0 commit comments