Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions crates/js-component-bindgen/src/function_bindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ impl FunctionBindgen<'_> {
r#"
if ({memory_idx_expr} !== null) {{
task.setReturnMemoryIdx({memory_idx_expr});
task.setReturnMemory({get_memory_fn_expr}());
task.setReturnMemory(({get_memory_fn_expr})());
}}
"#
);
Expand Down Expand Up @@ -1967,12 +1967,19 @@ impl Bindgen for FunctionBindgen<'_> {
}
}

// Argument lowering can await realloc and allow another task
// to run. Reinstall this task immediately before entering Wasm.
let call_wrapper = self.intrinsic(Intrinsic::WithGlobalCurrentTaskMetaFn);
uwriteln!(
self.src,
r#"
{vars_init}
try {{
{assignment_lhs} {call_prefix}{callee_invoke};
{assignment_lhs} {call_prefix}{call_wrapper}({{
taskID: task.id(),
componentIdx: task.componentIdx(),
fn: () => {callee_invoke},
}});
}} catch (err) {{
{call_err_cleanup}
}}
Expand Down Expand Up @@ -3228,7 +3235,10 @@ impl Bindgen for FunctionBindgen<'_> {
let result_var = format!("futureResult{tmp}");

// Optionally preform the lift for the future in question
match (self.is_async, self.for_import.unwrap_or_default()) {
match (
self.canonical_abi_async,
self.for_import.unwrap_or_default(),
) {
// It is possible for lifting to be called both at the *start* and *end* of
// a given function depending on how it called:
//
Expand Down Expand Up @@ -3542,7 +3552,10 @@ impl Bindgen for FunctionBindgen<'_> {
let result_var = format!("streamResult{tmp}");

// Optionally preform the lift for the stream in question
match (self.is_async, self.for_import.unwrap_or_default()) {
match (
self.canonical_abi_async,
self.for_import.unwrap_or_default(),
) {
// It is possible for lifting to be called both at the *start* and *end* of
// a given function depending on how it called:
//
Expand Down
27 changes: 22 additions & 5 deletions crates/js-component-bindgen/src/intrinsics/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ impl ComponentIntrinsic {
// Awaitable acquisition: takes the lock immediately when free,
// otherwise queues FIFO behind the current holder and earlier
// waiters. The resolved promise implies ownership.
async acquireExclusiveLock(taskID) {{
acquireExclusiveLock(taskID) {{
if (taskID === undefined || taskID === null) {{
throw new Error('exclusive lock requires the acquiring task id');
}}
Expand All @@ -586,7 +586,7 @@ impl ComponentIntrinsic {
componentIdx: this.#componentIdx,
queued: this.#lockWaiters.length,
}});
await new Promise((resolve) => {{
return new Promise((resolve) => {{
this.#lockWaiters.push({{ taskID, resolve }});
}});
}}
Expand Down Expand Up @@ -690,7 +690,7 @@ impl ComponentIntrinsic {

// TODO(threads): readyFn is normally on the thread
suspendTask(args) {{
const {{ task, readyFn }} = args;
const {{ task, readyFn, cancellable, onResume }} = args;
const taskID = task.id();
const componentIdx = task.componentIdx();
{debug_log_fn}('[{component_async_state_class}#suspendTask()]', {{
Expand All @@ -708,18 +708,27 @@ impl ComponentIntrinsic {
throw new Error(`task [${{taskID}}] already suspended`);
}}

const {{ promise, resolve, reject }} = {promise_with_resolvers_fn}();
let promise;
let resume;
if (onResume) {{
resume = () => onResume(!task.isCancelled());
}} else {{
const resolvers = {promise_with_resolvers_fn}();
promise = resolvers.promise;
resume = () => resolvers.resolve(!task.isCancelled());
}}
this.#addSuspendedTaskMeta({{
task,
taskID,
cancellable,
readyFn,
resume: () => {{
{debug_log_fn}('[{component_async_state_class}] resuming suspended task', {{
taskID,
componentIdx: this.#componentIdx,
}});
// TODO(threads): it's thread cancellation we should be checking for below, not task
resolve(!task.isCancelled());
resume();
}},
}});

Expand Down Expand Up @@ -751,6 +760,14 @@ impl ComponentIntrinsic {
return meta.task.isRejected() || meta.readyFn();
}}

suspendedTaskCancellable(taskID) {{
return !!this.#getSuspendedTaskMeta(taskID)?.cancellable;
}}

isTaskSuspended(taskID) {{
return this.#suspendedTasksByTaskID.has(taskID);
}}

suspendedTaskMetas() {{
return this.#suspendedTasksByTaskID.values();
}}
Expand Down
Loading
Loading