Skip to content

Commit 88e8326

Browse files
wip: fixup commented, code, start debugging other test case failures
1 parent b4e21ae commit 88e8326

File tree

2 files changed

+61
-212
lines changed

2 files changed

+61
-212
lines changed

crates/js-component-bindgen/src/function_bindgen.rs

Lines changed: 58 additions & 209 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use crate::intrinsics::js_helper::JsHelperIntrinsic;
1818
use crate::intrinsics::p3::async_future::AsyncFutureIntrinsic;
1919
use crate::intrinsics::p3::async_stream::AsyncStreamIntrinsic;
2020
use crate::intrinsics::p3::async_task::AsyncTaskIntrinsic;
21-
use crate::intrinsics::p3::host::HostIntrinsic;
2221
use crate::intrinsics::resource::ResourceIntrinsic;
2322
use crate::intrinsics::string::StringIntrinsic;
2423
use 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: &params,
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.

crates/js-component-bindgen/src/intrinsics/p3/host.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,10 @@ impl HostIntrinsic {
178178
const task = taskMeta.task;
179179
if (!task) {{ throw new Error('unexpectedly missing task in task meta during prepare call'); }}
180180
181+
// TODO: callee instance is coming up becasue the subtask's Task was removed already?
182+
181183
if (task.componentIdx() !== callerInstanceIdx) {{
182-
throw new Error(`task component idx [${{ task.componentIdx() }}] differs from caller [${{ callerInstanceIdx }}]`);
184+
throw new Error(`task component idx [${{ task.componentIdx() }}] differs from caller [${{ callerInstanceIdx }}] (callee ${{ calleeInstanceIdx }})`);
183185
}}
184186
185187
const directParams = storagePtr === -1;
@@ -295,9 +297,7 @@ impl HostIntrinsic {
295297
throw new Error(`unexpected param count [${{ paramCount }}], expected [${{ expectedParamCount }}]`);
296298
}}
297299
298-
console.log('BEFORE CALLBACK RESULT GET');
299300
let callbackResult = WebAssembly.promising(callee).apply(null, params);
300-
//let callbackResult = callee.apply(null, params);
301301
302302
// If a single call resolved the subtask, we can return immediately
303303
if (subtask.resolved()) {{

0 commit comments

Comments
 (0)