@@ -18,7 +18,6 @@ use crate::intrinsics::js_helper::JsHelperIntrinsic;
1818use crate :: intrinsics:: p3:: async_future:: AsyncFutureIntrinsic ;
1919use crate :: intrinsics:: p3:: async_stream:: AsyncStreamIntrinsic ;
2020use crate :: intrinsics:: p3:: async_task:: AsyncTaskIntrinsic ;
21- use crate :: intrinsics:: p3:: host:: HostIntrinsic ;
2221use crate :: intrinsics:: resource:: ResourceIntrinsic ;
2322use crate :: intrinsics:: string:: StringIntrinsic ;
2423use crate :: { ManagesIntrinsics , get_thrown_type, source} ;
@@ -237,22 +236,20 @@ impl FunctionBindgen<'_> {
237236 /// ```
238237 /// var [ ret0, ret1, ret2 ] =
239238 /// ```
240- fn write_result_assignment ( & mut self , amt : usize , results : & mut Vec < String > , is_async : bool ) {
241- // For async functions there is always a result returned and it's a single integer
242- // which indicates async state. This is a sort of "meta" result -- i.e. it shouldn't be counted
243- // as a regular function result but *should* be made available to the JS internal code.
244- if is_async {
245- uwrite ! ( self . src, "let ret = " ) ;
246- return ;
247- }
248- match ( is_async, amt) {
249- ( true , _) => { }
250- ( false , 0 ) => { }
251- ( false , 1 ) => {
239+ ///
240+ /// # Arguments
241+ ///
242+ /// * `amt` - number of results
243+ /// * `results` - list of variables that will be returned
244+ ///
245+ fn write_result_assignment ( & mut self , amt : usize , results : & mut Vec < String > ) {
246+ match amt {
247+ 0 => { }
248+ 1 => {
252249 uwrite ! ( self . src, "let ret = " ) ;
253250 results. push ( "ret" . to_string ( ) ) ;
254251 }
255- ( false , n ) => {
252+ n => {
256253 uwrite ! ( self . src, "var [" ) ;
257254 for i in 0 ..n {
258255 if i > 0 {
@@ -1274,7 +1271,7 @@ impl Bindgen for FunctionBindgen<'_> {
12741271
12751272 // Output result binding preamble (e.g. 'var ret =', 'var [ ret0, ret1] = exports...() ')
12761273 let sig_results_length = sig. results . len ( ) ;
1277- self . write_result_assignment ( sig_results_length, results, self . is_async ) ;
1274+ self . write_result_assignment ( sig_results_length, results) ;
12781275
12791276 // Write the rest of the result asignment -- calling the callee function
12801277 uwriteln ! (
@@ -1321,7 +1318,6 @@ impl Bindgen for FunctionBindgen<'_> {
13211318 // self.intrinsic(Intrinsic::AsyncTask(AsyncTaskIntrinsic::GetCurrentTask));
13221319 // let component_instance_idx = self.canon_opts.instance.as_u32();
13231320
1324-
13251321 let debug_log_fn = self . intrinsic ( Intrinsic :: DebugLog ) ;
13261322 uwriteln ! (
13271323 self . src,
@@ -1330,87 +1326,24 @@ impl Bindgen for FunctionBindgen<'_> {
13301326 async_ = async_. then_some( "async" ) . unwrap_or( "sync" ) ,
13311327 ) ;
13321328
1333- // // Detect whether we're executing in an async subtask
1334- // if *async_ {
1335- // uwriteln!(
1336- // self.src,
1337- // r#"
1338- // let inSubtask;
1339- // {{
1340- // const componentState = {get_or_create_async_state_fn}({component_instance_idx});
1341- // if (!componentState) {{ throw new Error('failed to lookup current component state'); }}
1342-
1343- // const taskMeta = {current_task_get_fn}({component_instance_idx});
1344- // if (!taskMeta) {{ throw new Error('failed to find current task metadata'); }}
1345-
1346- // const task = taskMeta.task;
1347- // if (!task) {{ throw new Error('missing/invalid task in current task metadata'); }}
1348-
1349- // inSubtask = task.getParentSubtask();
1350- // }}
1351- // "#,
1352- // );
1353- // }
1354-
1355- // Inject machinery for starting a 'current' task
1356- self . start_current_task (
1357- inst,
1358- * async_,
1359- & func. name ,
1360- self . canon_opts
1361- . callback
1362- . as_ref ( )
1363- . map ( |v| format ! ( "callback_{}" , v. as_u32( ) ) ) ,
1364- ) ;
1365-
1366- // // Detect async host imports and ensure that they are awaited indirectly
1367- // //
1368- // // This normally needs to be done when the following conditions hold:
1369- // // - We're running an async lifted export
1370- // // - 're running an async lifted export
1371- // //
1372- // // If we're running a sync lifted export, attempting to run an async import should be an immediate trap.
1373- // uwriteln!(self.src, "let inAsyncSubtask = false;");
1374- // if *async_ {
1375- // uwriteln!(
1376- // self.src,
1377- // r#"
1378- // console.log('DOING CALL INTERFACE');
1379- // {{
1380- // const componentState = {get_or_create_async_state_fn}({component_instance_idx});
1381- // if (!componentState) {{ throw new Error('failed to lookup current component state'); }}
1382-
1383- // const taskMeta = {current_task_get_fn}({component_instance_idx});
1384- // if (!taskMeta) {{ throw new Error('failed to find current task metadata'); }}
1385-
1386- // const task = taskMeta.task;
1387- // if (!task) {{ throw new Error('missing/invalid task in current task metadata'); }}
1388-
1389- // inAsyncSubtask = task.getParentSubtask() !== null;
1390- // }}
1391- // "#,
1392- // );
1393- // }
1329+ // // Inject machinery for starting a 'current' task
1330+ // self.start_current_task(
1331+ // inst,
1332+ // *async_,
1333+ // &func.name,
1334+ // self.canon_opts
1335+ // .callback
1336+ // .as_ref()
1337+ // .map(|v| format!("callback_{}", v.as_u32())),
1338+ // );
13941339
13951340 let results_length = if func. result . is_none ( ) { 0 } else { 1 } ;
1396- let ( maybe_async , maybe_await) = if self . requires_async_porcelain | async_ {
1397- ( "async " , " await ")
1341+ let maybe_await = if self . requires_async_porcelain | async_ {
1342+ " await "
13981343 } else {
1399- ( "" , "" )
1344+ ""
14001345 } ;
14011346
1402- // // Build the call
1403- // let call = if self.callee_resource_dynamic {
1404- // format!(
1405- // "{}.{}({})",
1406- // operands[0],
1407- // self.callee,
1408- // operands[1..].join(", ")
1409- // )
1410- // } else {
1411- // format!("{}({})", self.callee, operands.join(", "))
1412- // };
1413-
14141347 // Build the call
14151348 let call = if self . callee_resource_dynamic {
14161349 format ! (
@@ -1423,98 +1356,43 @@ impl Bindgen for FunctionBindgen<'_> {
14231356 format ! ( "{maybe_await} {}({})" , self . callee, operands. join( ", " ) )
14241357 } ;
14251358
1426- // // Build an intermediate function that *may* force resolution on the host side
1427- // // if we're in an async subtask. In the async subtask case, we must ask the host
1428- // // to peform the computation (by passing back the generated Promise, but not attempting to await it)
1429- // // and waiting for result from a synchronous function.
1430- // //
1431- // // If we're not in an async subtask, can call the relevant callee normally
1432- // uwriteln!(
1433- // self.src,
1434- // r#"
1435- // let doCall;
1436- // if (inAsyncSubtask) {{
1437- // doCall = async () => {{
1438- // let id = {start_host_promise_resolution_fn}({call});
1439- // await new Promise(resolve => {{
1440- // const waitInterval = setInterval(() => {{
1441- // const result = {check_host_promise_resolution_fn}(id);
1442- // if (result) {{
1443- // clearInterval(waitInterval);
1444- // resolve(result[0]);
1445- // }}
1446- // }}, 100);
1447- // }});
1448- // }};
1449- // }} else {{
1450- // console.log('NOT IN SUBTASK');
1451- // doCall = {maybe_async} () => {{ return {maybe_await} {call}; }};
1452- // }}
1453- // "#,
1454- // );
1455-
1456- // if self.err == ErrHandling::ResultCatchHandler {
1457- // // result<_, string> allows JS error coercion only, while
1458- // // any other result type will trap for arbitrary JS errors.
1459- // let err_payload = if let (_, Some(Type::Id(err_ty))) =
1460- // get_thrown_type(self.resolve, func.result).unwrap()
1461- // {
1462- // match &self.resolve.types[*err_ty].kind {
1463- // TypeDefKind::Type(Type::String) => {
1464- // self.intrinsic(Intrinsic::GetErrorPayloadString)
1465- // }
1466- // _ => self.intrinsic(Intrinsic::GetErrorPayload),
1467- // }
1468- // } else {
1469- // self.intrinsic(Intrinsic::GetErrorPayload)
1470- // };
1471- // uwriteln!(
1472- // self.src,
1473- // r#"
1474- // let ret;
1475- // try {{
1476- // ret = {{ tag: 'ok', val: {maybe_await} doCall() }};
1477- // }} catch (e) {{
1478- // ret = {{ tag: 'err', val: {err_payload}(e) }};
1479- // }}
1480- // "#,
1481- // );
1482- // results.push("ret".to_string());
1483- // } else {
1484- // self.write_result_assignment(results_length, results, self.is_async);
1485- // uwriteln!(self.src, "{maybe_await} doCall();");
1486- // }
1487-
1488- if self . err == ErrHandling :: ResultCatchHandler {
1489- // result<_, string> allows JS error coercion only, while
1490- // any other result type will trap for arbitrary JS errors.
1491- let err_payload = if let ( _, Some ( Type :: Id ( err_ty) ) ) =
1492- get_thrown_type ( self . resolve , func. result ) . unwrap ( )
1493- {
1494- match & self . resolve . types [ * err_ty] . kind {
1495- TypeDefKind :: Type ( Type :: String ) => {
1496- self . intrinsic ( Intrinsic :: GetErrorPayloadString )
1359+ match self . err {
1360+ // If configured to do *no* error handling at all or throw
1361+ // error objects directly, we can simply perform the call
1362+ ErrHandling :: None | ErrHandling :: ThrowResultErr => {
1363+ self . write_result_assignment ( results_length, results) ;
1364+ uwriteln ! ( self . src, "{call};" ) ;
1365+ }
1366+ // If configured to force all thrown errors into result objects,
1367+ // then we add a try/catch around the call
1368+ ErrHandling :: ResultCatchHandler => {
1369+ // result<_, string> allows JS error coercion only, while
1370+ // any other result type will trap for arbitrary JS errors.
1371+ let err_payload = if let ( _, Some ( Type :: Id ( err_ty) ) ) =
1372+ get_thrown_type ( self . resolve , func. result ) . unwrap ( )
1373+ {
1374+ match & self . resolve . types [ * err_ty] . kind {
1375+ TypeDefKind :: Type ( Type :: String ) => {
1376+ self . intrinsic ( Intrinsic :: GetErrorPayloadString )
1377+ }
1378+ _ => self . intrinsic ( Intrinsic :: GetErrorPayload ) ,
14971379 }
1498- _ => self . intrinsic ( Intrinsic :: GetErrorPayload ) ,
1499- }
1500- } else {
1501- self . intrinsic ( Intrinsic :: GetErrorPayload )
1502- } ;
1503- uwriteln ! (
1504- self . src,
1505- r#"
1380+ } else {
1381+ self . intrinsic ( Intrinsic :: GetErrorPayload )
1382+ } ;
1383+ uwriteln ! (
1384+ self . src,
1385+ r#"
15061386 let ret;
15071387 try {{
15081388 ret = {{ tag: 'ok', val: {call} }};
15091389 }} catch (e) {{
15101390 ret = {{ tag: 'err', val: {err_payload}(e) }};
15111391 }}
15121392 "# ,
1513- ) ;
1514- results. push ( "ret" . to_string ( ) ) ;
1515- } else {
1516- self . write_result_assignment ( results_length, results, self . is_async ) ;
1517- uwriteln ! ( self . src, "{call};" ) ;
1393+ ) ;
1394+ results. push ( "ret" . to_string ( ) ) ;
1395+ }
15181396 }
15191397
15201398 uwriteln ! (
@@ -1578,10 +1456,10 @@ impl Bindgen for FunctionBindgen<'_> {
15781456 self . clear_resource_borrows = false ;
15791457 }
15801458
1581- // For non-async calls, the current task can end immediately
1582- if !async_ {
1583- self . end_current_task ( ) ;
1584- }
1459+ // // For non-async calls, the current task can end immediately
1460+ // if !async_ {
1461+ // self.end_current_task();
1462+ // }
15851463 }
15861464
15871465 Instruction :: Return {
@@ -1624,31 +1502,6 @@ impl Bindgen for FunctionBindgen<'_> {
16241502
16251503 assert ! ( !self . is_async, "async functions should use AsyncTaskReturn" ) ;
16261504
1627- // // TODO: this shouldn't be here, handle via AsyncTaskReturn
1628- // // see: https://github.com/bytecodealliance/wit-bindgen/pull/1414
1629- // if self.is_async {
1630- // // Forward to handling of async task return
1631- // let fn_name = format!("[task-return]{}", func.name);
1632- // let params = {
1633- // let mut container = Vec::new();
1634- // let mut flattened_types = FlatTypes::new(&mut container);
1635- // for (_name, ty) in func.params.iter() {
1636- // self.resolve.push_flat(ty, &mut flattened_types);
1637- // }
1638- // flattened_types.to_vec()
1639- // };
1640- // self.emit(
1641- // resolve,
1642- // &Instruction::AsyncTaskReturn {
1643- // name: &fn_name,
1644- // params: ¶ms,
1645- // },
1646- // operands,
1647- // results,
1648- // );
1649- // return;
1650- // }
1651-
16521505 // Depending how many values are on the stack after returning, we must execute differently.
16531506 //
16541507 // In particular, if this function is async (distinct from whether async porcelain was necessary or not),
@@ -2333,10 +2186,6 @@ impl Bindgen for FunctionBindgen<'_> {
23332186 self . is_async,
23342187 "non-async functions should not be performing async returns (func {name})" ,
23352188 ) ;
2336- assert ! (
2337- self . post_return. is_none( ) ,
2338- "async fn cannot have post_return specified (func {name})"
2339- ) ;
23402189
23412190 // If we're dealing with an async call, then `ret` is actually the
23422191 // state of async behavior.
0 commit comments