Repository: bytecodealliance/wasm-tools
Pull request #2140 (2025-04-14 15:23:56)

add `task.cancel` intrinsic
As with `subtask.cancel`, this hasn't been added to the spec yet, so I made up a binary discriminant for it.  We can sync that with the spec once it has been updated.


Patch:
diff --git a/crates/wasm-encoder/src/component/builder.rs b/crates/wasm-encoder/src/component/builder.rs
index c0c2c000..2b3cb596 100644
--- a/crates/wasm-encoder/src/component/builder.rs
+++ b/crates/wasm-encoder/src/component/builder.rs
@@ -407,6 +407,12 @@ impl ComponentBuilder {
         inc(&mut self.core_funcs)
     }
 
+    /// Declares a new `task.cancel` intrinsic.
+    pub fn task_cancel(&mut self) -> u32 {
+        self.canonical_functions().task_cancel();
+        inc(&mut self.core_funcs)
+    }
+
     /// Declares a new `context.get` intrinsic.
     pub fn context_get(&mut self, i: u32) -> u32 {
         self.canonical_functions().context_get(i);
diff --git a/crates/wasm-encoder/src/component/canonicals.rs b/crates/wasm-encoder/src/component/canonicals.rs
index efee0cf6..bd1c4ba0 100644
--- a/crates/wasm-encoder/src/component/canonicals.rs
+++ b/crates/wasm-encoder/src/component/canonicals.rs
@@ -210,6 +210,13 @@ impl CanonicalFunctionSection {
         self
     }
 
+    /// Defines a function to acknowledge cancellation of the current task.
+    pub fn task_cancel(&mut self) -> &mut Self {
+        self.bytes.push(0x25);
+        self.num_added += 1;
+        self
+    }
+
     /// Defines a new `context.get` intrinsic of the ith slot.
     pub fn context_get(&mut self, i: u32) -> &mut Self {
         self.bytes.push(0x0a);
diff --git a/crates/wasm-encoder/src/reencode/component.rs b/crates/wasm-encoder/src/reencode/component.rs
index 9b0d89b9..3d50dfca 100644
--- a/crates/wasm-encoder/src/reencode/component.rs
+++ b/crates/wasm-encoder/src/reencode/component.rs
@@ -977,6 +977,9 @@ pub mod component_utils {
                     options.iter().map(|o| reencoder.canonical_option(*o)),
                 );
             }
+            wasmparser::CanonicalFunction::TaskCancel => {
+                section.task_cancel();
+            }
             wasmparser::CanonicalFunction::ContextGet(i) => {
                 section.context_get(i);
             }
diff --git a/crates/wasmparser/src/readers/component/canonicals.rs b/crates/wasmparser/src/readers/component/canonicals.rs
index b75d0e43..f7160544 100644
--- a/crates/wasmparser/src/readers/component/canonicals.rs
+++ b/crates/wasmparser/src/readers/component/canonicals.rs
@@ -98,6 +98,8 @@ pub enum CanonicalFunction {
         /// The canonical options for the function.
         options: Box<[CanonicalOption]>,
     },
+    /// A function to acknowledge cancellation of the current task.
+    TaskCancel,
     /// A `context.get` intrinsic for the `i`th slot of task-local storage.
     ContextGet(u32),
     /// A `context.set` intrinsic for the `i`th slot of task-local storage.
@@ -368,6 +370,7 @@ impl<'a> FromReader<'a> for CanonicalFunction {
             0x24 => CanonicalFunction::SubtaskCancel {
                 async_: reader.read()?,
             },
+            0x25 => CanonicalFunction::TaskCancel,
             0x40 => CanonicalFunction::ThreadSpawnRef {
                 func_ty_index: reader.read()?,
             },
diff --git a/crates/wasmparser/src/validator/component.rs b/crates/wasmparser/src/validator/component.rs
index e2f42778..233b3eb0 100644
--- a/crates/wasmparser/src/validator/component.rs
+++ b/crates/wasmparser/src/validator/component.rs
@@ -965,6 +965,7 @@ impl ComponentState {
             CanonicalFunction::TaskReturn { result, options } => {
                 self.task_return(&result, &options, types, offset)
             }
+            CanonicalFunction::TaskCancel => self.task_cancel(types, offset),
             CanonicalFunction::ContextGet(i) => self.context_get(i, types, offset),
             CanonicalFunction::ContextSet(i) => self.context_set(i, types, offset),
             CanonicalFunction::Yield { async_ } => self.yield_(async_, types, offset),
@@ -1210,6 +1211,19 @@ impl ComponentState {
         Ok(())
     }
 
+    fn task_cancel(&mut self, types: &mut TypeAlloc, offset: usize) -> Result<()> {
+        if !self.features.cm_async() {
+            bail!(
+                offset,
+                "`task.cancel` requires the component model async feature"
+            )
+        }
+
+        self.core_funcs
+            .push(types.intern_func_type(FuncType::new([], []), offset));
+        Ok(())
+    }
+
     fn context_get(&mut self, i: u32, types: &mut TypeAlloc, offset: usize) -> Result<()> {
         if !self.features.cm_async() {
             bail!(
diff --git a/crates/wasmprinter/src/component.rs b/crates/wasmprinter/src/component.rs
index 258cd726..c54516bd 100644
--- a/crates/wasmprinter/src/component.rs
+++ b/crates/wasmprinter/src/component.rs
@@ -930,6 +930,9 @@ impl Printer<'_, '_> {
                         Ok(())
                     })?;
                 }
+                CanonicalFunction::TaskCancel => {
+                    self.print_intrinsic(state, "canon task.cancel", &|_, _| Ok(()))?;
+                }
                 CanonicalFunction::ContextGet(i) => {
                     self.print_intrinsic(state, "canon context.get", &|me, _state| {
                         write!(me.result, " i32 {i}")?;
diff --git a/crates/wast/src/component/binary.rs b/crates/wast/src/component/binary.rs
index 43c9a118..89d4f3fb 100644
--- a/crates/wast/src/component/binary.rs
+++ b/crates/wast/src/component/binary.rs
@@ -380,6 +380,10 @@ impl<'a> Encoder<'a> {
                         info.opts.iter().map(Into::into),
                     );
                 }
+                CoreFuncKind::TaskCancel => {
+                    self.core_func_names.push(name);
+                    self.funcs.task_cancel();
+                }
                 CoreFuncKind::ContextGet(i) => {
                     self.core_func_names.push(name);
                     self.funcs.context_get(*i);
diff --git a/crates/wast/src/component/func.rs b/crates/wast/src/component/func.rs
index fc01a337..f35a9f5a 100644
--- a/crates/wast/src/component/func.rs
+++ b/crates/wast/src/component/func.rs
@@ -56,6 +56,7 @@ pub enum CoreFuncKind<'a> {
     ThreadAvailableParallelism(CanonThreadAvailableParallelism),
     BackpressureSet,
     TaskReturn(CanonTaskReturn<'a>),
+    TaskCancel,
     ContextGet(u32),
     ContextSet(u32),
     Yield(CanonYield),
@@ -122,6 +123,9 @@ impl<'a> CoreFuncKind<'a> {
             Ok(CoreFuncKind::BackpressureSet)
         } else if l.peek::<kw::task_return>()? {
             Ok(CoreFuncKind::TaskReturn(parser.parse()?))
+        } else if l.peek::<kw::task_cancel>()? {
+            parser.parse::<kw::task_cancel>()?;
+            Ok(CoreFuncKind::TaskCancel)
         } else if l.peek::<kw::context_get>()? {
             parser.parse::<kw::context_get>()?;
             parser.parse::<kw::i32>()?;
diff --git a/crates/wast/src/component/resolve.rs b/crates/wast/src/component/resolve.rs
index 8bd53c84..16c1b025 100644
--- a/crates/wast/src/component/resolve.rs
+++ b/crates/wast/src/component/resolve.rs
@@ -396,6 +396,7 @@ impl<'a> Resolver<'a> {
                 }
                 CoreFuncKind::ThreadAvailableParallelism(_)
                 | CoreFuncKind::BackpressureSet
+                | CoreFuncKind::TaskCancel
                 | CoreFuncKind::Yield(_)
                 | CoreFuncKind::SubtaskDrop
                 | CoreFuncKind::SubtaskCancel(_)
diff --git a/crates/wast/src/lib.rs b/crates/wast/src/lib.rs
index 8c92d8f9..cb4a1771 100644
--- a/crates/wast/src/lib.rs
+++ b/crates/wast/src/lib.rs
@@ -559,6 +559,7 @@ pub mod kw {
     custom_keyword!(thread_available_parallelism = "thread.available_parallelism");
     custom_keyword!(backpressure_set = "backpressure.set");
     custom_keyword!(task_return = "task.return");
+    custom_keyword!(task_cancel = "task.cancel");
     custom_keyword!(yield_ = "yield");
     custom_keyword!(subtask_drop = "subtask.drop");
     custom_keyword!(subtask_cancel = "subtask.cancel");
diff --git a/crates/wit-component/src/dummy.rs b/crates/wit-component/src/dummy.rs
index 58be4468..a18b39bd 100644
--- a/crates/wit-component/src/dummy.rs
+++ b/crates/wit-component/src/dummy.rs
@@ -372,6 +372,7 @@ fn push_tys(dst: &mut String, desc: &str, params: &[WasmType]) {
 fn push_root_async_intrinsics(dst: &mut String) {
     dst.push_str(
         r#"
+(import "[export]$root" "[task-cancel]" (func))
 (import "$root" "[backpressure-set]" (func (param i32)))
 (import "$root" "[waitable-set-new]" (func (result i32)))
 (import "$root" "[waitable-set-wait]" (func (param i32 i32) (result i32)))
@@ -380,6 +381,7 @@ fn push_root_async_intrinsics(dst: &mut String) {
 (import "$root" "[waitable-join]" (func (param i32 i32)))
 (import "$root" "[yield]" (func))
 (import "$root" "[subtask-drop]" (func (param i32)))
+(import "$root" "[subtask-cancel]" (func (param i32) (result i32)))
 (import "$root" "[error-context-new-utf8]" (func (param i32 i32) (result i32)))
 (import "$root" "[error-context-new-utf16]" (func (param i32 i32) (result i32)))
 (import "$root" "[error-context-new-latin1+utf16]" (func (param i32 i32) (result i32)))
diff --git a/crates/wit-component/src/encoding.rs b/crates/wit-component/src/encoding.rs
index 29577843..b1cb7c13 100644
--- a/crates/wit-component/src/encoding.rs
+++ b/crates/wit-component/src/encoding.rs
@@ -1826,6 +1826,10 @@ impl<'a> EncodingState<'a> {
                 let index = self.component.context_set(*n);
                 Ok((ExportKind::Func, index))
             }
+            Import::ExportedTaskCancel => {
+                let index = self.component.task_cancel();
+                Ok((ExportKind::Func, index))
+            }
         }
     }
 
@@ -2188,6 +2192,7 @@ impl<'a> Shims<'a> {
                 | Import::ExportedResourceDrop(..)
                 | Import::ExportedResourceRep(..)
                 | Import::ExportedResourceNew(..)
+                | Import::ExportedTaskCancel
                 | Import::ErrorContextDrop
                 | Import::BackpressureSet
                 | Import::Yield { .. }
diff --git a/crates/wit-component/src/encoding/world.rs b/crates/wit-component/src/encoding/world.rs
index 79d4dd84..c52202bb 100644
--- a/crates/wit-component/src/encoding/world.rs
+++ b/crates/wit-component/src/encoding/world.rs
@@ -425,7 +425,8 @@ impl<'a> ComponentWorld<'a> {
                 | Import::SubtaskCancel { .. }
                 | Import::ErrorContextNew { .. }
                 | Import::ErrorContextDebugMessage { .. }
-                | Import::ErrorContextDrop => {}
+                | Import::ErrorContextDrop
+                | Import::ExportedTaskCancel => {}
             }
         }
     }
diff --git a/crates/wit-component/src/validation.rs b/crates/wit-component/src/validation.rs
index 86888de5..9ebc5377 100644
--- a/crates/wit-component/src/validation.rs
+++ b/crates/wit-component/src/validation.rs
@@ -255,6 +255,11 @@ pub enum Import {
     /// well.
     ExportedTaskReturn(WorldKey, Option<InterfaceId>, String, Option<Type>),
 
+    /// A `canon task.cancel` intrinsic for an exported function.
+    ///
+    /// This allows an exported function to acknowledge a `CANCELLED` event.
+    ExportedTaskCancel,
+
     /// The `context.get` intrinsic for the nth slot of storage.
     ContextGet(u32),
     /// The `context.set` intrinsic for the nth slot of storage.
@@ -824,6 +829,14 @@ impl ImportMap {
                     func.result,
                 )));
             }
+            if Some(name) == names.task_cancel() {
+                if async_ {
+                    bail!("async `task.cancel` calls not supported");
+                }
+                let expected = FuncType::new([], []);
+                validate_func_sig(name, &expected, ty)?;
+                return Ok(Some(Import::ExportedTaskCancel));
+            }
         }
 
         // Looks for `[$prefix-N]foo` within `name`. If found then `foo` is
@@ -1409,6 +1422,7 @@ trait NameMangling {
     fn resource_new_name<'a>(&self, s: &'a str) -> Option<&'a str>;
     fn resource_rep_name<'a>(&self, s: &'a str) -> Option<&'a str>;
     fn task_return_name<'a>(&self, s: &'a str) -> Option<&'a str>;
+    fn task_cancel(&self) -> Option<&str>;
     fn backpressure_set(&self) -> Option<&str>;
     fn waitable_set_new(&self) -> Option<&str>;
     fn waitable_set_wait(&self) -> Option<&str>;
@@ -1488,6 +1502,9 @@ impl NameMangling for Standard {
         _ = s;
         None
     }
+    fn task_cancel(&self) -> Option<&str> {
+        None
+    }
     fn backpressure_set(&self) -> Option<&str> {
         None
     }
@@ -1684,6 +1701,9 @@ impl NameMangling for Legacy {
     fn task_return_name<'a>(&self, s: &'a str) -> Option<&'a str> {
         s.strip_prefix("[task-return]")
     }
+    fn task_cancel(&self) -> Option<&str> {
+        Some("[task-cancel]")
+    }
     fn backpressure_set(&self) -> Option<&str> {
         Some("[backpressure-set]")
     }
diff --git a/src/bin/wasm-tools/dump.rs b/src/bin/wasm-tools/dump.rs
index 75e2efcb..525e08aa 100644
--- a/src/bin/wasm-tools/dump.rs
+++ b/src/bin/wasm-tools/dump.rs
@@ -424,6 +424,7 @@ impl<'a> Dump<'a> {
                             | CanonicalFunction::ThreadAvailableParallelism
                             | CanonicalFunction::BackpressureSet
                             | CanonicalFunction::TaskReturn { .. }
+                            | CanonicalFunction::TaskCancel
                             | CanonicalFunction::ContextGet { .. }
                             | CanonicalFunction::ContextSet { .. }
                             | CanonicalFunction::WaitableSetNew


Test patch:
diff --git a/crates/wit-component/tests/components/async-builtins/component.wat b/crates/wit-component/tests/components/async-builtins/component.wat
index 55673a87..05fa5119 100644
--- a/crates/wit-component/tests/components/async-builtins/component.wat
+++ b/crates/wit-component/tests/components/async-builtins/component.wat
@@ -1,46 +1,47 @@
 (component
   (core module (;0;)
     (type (;0;) (func (param i32)))
-    (type (;1;) (func (param i32 i32)))
-    (type (;2;) (func (result i32)))
-    (type (;3;) (func (param i32 i32) (result i32)))
-    (type (;4;) (func))
+    (type (;1;) (func))
+    (type (;2;) (func (param i32 i32)))
+    (type (;3;) (func (result i32)))
+    (type (;4;) (func (param i32 i32) (result i32)))
     (type (;5;) (func (param i32) (result i32)))
     (type (;6;) (func (param i32 i32 i32 i32) (result i32)))
     (import "$root" "[backpressure-set]" (func (;0;) (type 0)))
-    (import "[export]$root" "[task-return]foo" (func (;1;) (type 1)))
-    (import "[export]foo:foo/bar" "[task-return]foo" (func (;2;) (type 1)))
-    (import "$root" "[waitable-set-new]" (func (;3;) (type 2)))
-    (import "$root" "[waitable-set-wait]" (func (;4;) (type 3)))
-    (import "$root" "[waitable-set-poll]" (func (;5;) (type 3)))
-    (import "$root" "[waitable-set-drop]" (func (;6;) (type 0)))
-    (import "$root" "[waitable-join]" (func (;7;) (type 1)))
-    (import "$root" "[yield]" (func (;8;) (type 4)))
-    (import "$root" "[subtask-drop]" (func (;9;) (type 0)))
-    (import "$root" "[subtask-cancel]" (func (;10;) (type 5)))
-    (import "$root" "[error-context-new-utf8]" (func (;11;) (type 3)))
-    (import "$root" "[error-context-new-utf16]" (func (;12;) (type 3)))
-    (import "$root" "[error-context-new-latin1+utf16]" (func (;13;) (type 3)))
-    (import "$root" "[error-context-debug-message-utf8]" (func (;14;) (type 1)))
-    (import "$root" "[error-context-debug-message-utf16]" (func (;15;) (type 1)))
-    (import "$root" "[error-context-debug-message-latin1+utf16]" (func (;16;) (type 1)))
-    (import "$root" "[error-context-drop]" (func (;17;) (type 0)))
-    (import "$root" "[context-get-0]" (func (;18;) (type 2)))
-    (import "$root" "[context-get-1]" (func (;19;) (type 2)))
-    (import "$root" "[context-set-0]" (func (;20;) (type 0)))
-    (import "$root" "[context-set-1]" (func (;21;) (type 0)))
+    (import "[export]$root" "[task-cancel]" (func (;1;) (type 1)))
+    (import "[export]$root" "[task-return]foo" (func (;2;) (type 2)))
+    (import "[export]foo:foo/bar" "[task-return]foo" (func (;3;) (type 2)))
+    (import "$root" "[waitable-set-new]" (func (;4;) (type 3)))
+    (import "$root" "[waitable-set-wait]" (func (;5;) (type 4)))
+    (import "$root" "[waitable-set-poll]" (func (;6;) (type 4)))
+    (import "$root" "[waitable-set-drop]" (func (;7;) (type 0)))
+    (import "$root" "[waitable-join]" (func (;8;) (type 2)))
+    (import "$root" "[yield]" (func (;9;) (type 1)))
+    (import "$root" "[subtask-drop]" (func (;10;) (type 0)))
+    (import "$root" "[subtask-cancel]" (func (;11;) (type 5)))
+    (import "$root" "[error-context-new-utf8]" (func (;12;) (type 4)))
+    (import "$root" "[error-context-new-utf16]" (func (;13;) (type 4)))
+    (import "$root" "[error-context-new-latin1+utf16]" (func (;14;) (type 4)))
+    (import "$root" "[error-context-debug-message-utf8]" (func (;15;) (type 2)))
+    (import "$root" "[error-context-debug-message-utf16]" (func (;16;) (type 2)))
+    (import "$root" "[error-context-debug-message-latin1+utf16]" (func (;17;) (type 2)))
+    (import "$root" "[error-context-drop]" (func (;18;) (type 0)))
+    (import "$root" "[context-get-0]" (func (;19;) (type 3)))
+    (import "$root" "[context-get-1]" (func (;20;) (type 3)))
+    (import "$root" "[context-set-0]" (func (;21;) (type 0)))
+    (import "$root" "[context-set-1]" (func (;22;) (type 0)))
     (memory (;0;) 1)
-    (export "[async-lift-stackful]foo" (func 22))
-    (export "[async-lift-stackful]foo:foo/bar#foo" (func 23))
+    (export "[async-lift-stackful]foo" (func 23))
+    (export "[async-lift-stackful]foo:foo/bar#foo" (func 24))
     (export "memory" (memory 0))
-    (export "cabi_realloc" (func 24))
-    (func (;22;) (type 1) (param i32 i32)
+    (export "cabi_realloc" (func 25))
+    (func (;23;) (type 2) (param i32 i32)
       unreachable
     )
-    (func (;23;) (type 1) (param i32 i32)
+    (func (;24;) (type 2) (param i32 i32)
       unreachable
     )
-    (func (;24;) (type 6) (param i32 i32 i32 i32) (result i32)
+    (func (;25;) (type 6) (param i32 i32 i32 i32) (result i32)
       unreachable
     )
     (@producers
@@ -191,13 +192,15 @@
     (export "[context-set-0]" (func 18))
     (export "[context-set-1]" (func 19))
   )
-  (alias core export 0 "8" (core func (;20;)))
+  (core func (;20;) (canon task.cancel))
+  (alias core export 0 "8" (core func (;21;)))
   (core instance (;2;)
-    (export "[task-return]foo" (func 20))
+    (export "[task-cancel]" (func 20))
+    (export "[task-return]foo" (func 21))
   )
-  (alias core export 0 "9" (core func (;21;)))
+  (alias core export 0 "9" (core func (;22;)))
   (core instance (;3;)
-    (export "[task-return]foo" (func 21))
+    (export "[task-return]foo" (func 22))
   )
   (core instance (;4;) (instantiate 0
       (with "$root" (instance 1))
@@ -207,41 +210,41 @@
   )
   (alias core export 4 "memory" (core memory (;0;)))
   (alias core export 0 "$imports" (core table (;0;)))
-  (core func (;22;) (canon waitable-set.wait (memory 0)))
-  (core func (;23;) (canon waitable-set.poll (memory 0)))
-  (core func (;24;) (canon error-context.new (memory 0) string-encoding=utf8))
-  (core func (;25;) (canon error-context.new (memory 0) string-encoding=utf16))
-  (core func (;26;) (canon error-context.new (memory 0) string-encoding=latin1+utf16))
-  (alias core export 4 "cabi_realloc" (core func (;27;)))
-  (core func (;28;) (canon error-context.debug-message (memory 0) (realloc 27) string-encoding=utf8))
-  (core func (;29;) (canon error-context.debug-message (memory 0) (realloc 27) string-encoding=utf16))
-  (core func (;30;) (canon error-context.debug-message (memory 0) (realloc 27) string-encoding=latin1+utf16))
-  (core func (;31;) (canon task.return (result string) (memory 0) string-encoding=utf8))
+  (core func (;23;) (canon waitable-set.wait (memory 0)))
+  (core func (;24;) (canon waitable-set.poll (memory 0)))
+  (core func (;25;) (canon error-context.new (memory 0) string-encoding=utf8))
+  (core func (;26;) (canon error-context.new (memory 0) string-encoding=utf16))
+  (core func (;27;) (canon error-context.new (memory 0) string-encoding=latin1+utf16))
+  (alias core export 4 "cabi_realloc" (core func (;28;)))
+  (core func (;29;) (canon error-context.debug-message (memory 0) (realloc 28) string-encoding=utf8))
+  (core func (;30;) (canon error-context.debug-message (memory 0) (realloc 28) string-encoding=utf16))
+  (core func (;31;) (canon error-context.debug-message (memory 0) (realloc 28) string-encoding=latin1+utf16))
   (core func (;32;) (canon task.return (result string) (memory 0) string-encoding=utf8))
+  (core func (;33;) (canon task.return (result string) (memory 0) string-encoding=utf8))
   (core instance (;5;)
     (export "$imports" (table 0))
-    (export "0" (func 22))
-    (export "1" (func 23))
-    (export "2" (func 24))
-    (export "3" (func 25))
-    (export "4" (func 26))
-    (export "5" (func 28))
-    (export "6" (func 29))
-    (export "7" (func 30))
-    (export "8" (func 31))
-    (export "9" (func 32))
+    (export "0" (func 23))
+    (export "1" (func 24))
+    (export "2" (func 25))
+    (export "3" (func 26))
+    (export "4" (func 27))
+    (export "5" (func 29))
+    (export "6" (func 30))
+    (export "7" (func 31))
+    (export "8" (func 32))
+    (export "9" (func 33))
   )
   (core instance (;6;) (instantiate 2
       (with "" (instance 5))
     )
   )
   (type (;0;) (func (param "s" string) (result string)))
-  (alias core export 4 "[async-lift-stackful]foo" (core func (;33;)))
-  (func (;0;) (type 0) (canon lift (core func 33) (memory 0) (realloc 27) string-encoding=utf8 async))
+  (alias core export 4 "[async-lift-stackful]foo" (core func (;34;)))
+  (func (;0;) (type 0) (canon lift (core func 34) (memory 0) (realloc 28) string-encoding=utf8 async))
   (export (;1;) "foo" (func 0))
   (type (;1;) (func (param "s" string) (result string)))
-  (alias core export 4 "[async-lift-stackful]foo:foo/bar#foo" (core func (;34;)))
-  (func (;2;) (type 1) (canon lift (core func 34) (memory 0) (realloc 27) string-encoding=utf8 async))
+  (alias core export 4 "[async-lift-stackful]foo:foo/bar#foo" (core func (;35;)))
+  (func (;2;) (type 1) (canon lift (core func 35) (memory 0) (realloc 28) string-encoding=utf8 async))
   (component (;0;)
     (type (;0;) (func (param "s" string) (result string)))
     (import "import-func-foo" (func (;0;) (type 0)))
diff --git a/crates/wit-component/tests/components/async-builtins/module.wat b/crates/wit-component/tests/components/async-builtins/module.wat
index 43a727c1..d76d09a0 100644
--- a/crates/wit-component/tests/components/async-builtins/module.wat
+++ b/crates/wit-component/tests/components/async-builtins/module.wat
@@ -1,5 +1,6 @@
 (module
   (import "$root" "[backpressure-set]" (func (param i32)))
+  (import "[export]$root" "[task-cancel]" (func))
   (import "[export]$root" "[task-return]foo" (func (param i32 i32)))
   (import "[export]foo:foo/bar" "[task-return]foo" (func (param i32 i32)))
   (import "$root" "[waitable-set-new]" (func (result i32)))
diff --git a/tests/cli/component-model-async/task-builtins.wast b/tests/cli/component-model-async/task-builtins.wast
index 9c87157c..97616ad1 100644
--- a/tests/cli/component-model-async/task-builtins.wast
+++ b/tests/cli/component-model-async/task-builtins.wast
@@ -69,6 +69,15 @@
   (core func (canon task.return (result u32) (memory $i "m")))
 )
 
+;; task.cancel
+(component
+  (core module $m
+    (import "" "task.cancel" (func $task-cancel))
+  )
+  (core func $task-cancel (canon task.cancel))
+  (core instance $i (instantiate $m (with "" (instance (export "task.cancel" (func $task-cancel))))))
+)
+
 ;; waitable-set.new
 (component
   (core module $m (import "" "waitable-set.new" (func (result i32))))
@@ -309,6 +318,8 @@
   (canon backpressure.set (core func))
   (core func (canon task.return))
   (canon task.return (core func))
+  (core func (canon task.cancel))
+  (canon task.cancel (core func))
   (core func (canon subtask.drop))
   (canon subtask.drop (core func))
   (core func (canon subtask.cancel))
diff --git a/tests/cli/missing-features/component-model/async.wast b/tests/cli/missing-features/component-model/async.wast
index 980a7f23..b6c0167a 100644
--- a/tests/cli/missing-features/component-model/async.wast
+++ b/tests/cli/missing-features/component-model/async.wast
@@ -54,6 +54,18 @@
   "`task.return` requires the component model async feature"
 )
 
+;; task.cancel
+(assert_invalid
+  (component
+    (core module $m
+      (import "" "task.cancel" (func $task-cancel))
+    )
+    (core func $task-cancel (canon task.cancel))
+    (core instance $i (instantiate $m (with "" (instance (export "task.cancel" (func $task-cancel))))))
+  )
+  "`task.cancel` requires the component model async feature"
+)
+
 ;; waitable-set.new
 (assert_invalid
   (component (core func (canon waitable-set.new)))
diff --git a/tests/snapshots/cli/component-model-async/task-builtins.wast.json b/tests/snapshots/cli/component-model-async/task-builtins.wast.json
index 481bcfda..17c33219 100644
--- a/tests/snapshots/cli/component-model-async/task-builtins.wast.json
+++ b/tests/snapshots/cli/component-model-async/task-builtins.wast.json
@@ -61,169 +61,175 @@
       "module_type": "binary"
     },
     {
-      "type": "assert_invalid",
-      "line": 81,
+      "type": "module",
+      "line": 82,
       "filename": "task-builtins.9.wasm",
+      "module_type": "binary"
+    },
+    {
+      "type": "assert_invalid",
+      "line": 90,
+      "filename": "task-builtins.10.wasm",
       "module_type": "binary",
       "text": "type mismatch for export `waitable-set.new` of module instantiation argument ``"
     },
     {
       "type": "module",
-      "line": 90,
-      "filename": "task-builtins.10.wasm",
+      "line": 99,
+      "filename": "task-builtins.11.wasm",
       "module_type": "binary"
     },
     {
       "type": "assert_invalid",
-      "line": 102,
-      "filename": "task-builtins.11.wasm",
+      "line": 111,
+      "filename": "task-builtins.12.wasm",
       "module_type": "binary",
       "text": "type mismatch for export `waitable-set.wait` of module instantiation argument ``"
     },
     {
       "type": "module",
-      "line": 115,
-      "filename": "task-builtins.12.wasm",
+      "line": 124,
+      "filename": "task-builtins.13.wasm",
       "module_type": "binary"
     },
     {
       "type": "assert_invalid",
-      "line": 127,
-      "filename": "task-builtins.13.wasm",
+      "line": 136,
+      "filename": "task-builtins.14.wasm",
       "module_type": "binary",
       "text": "type mismatch for export `waitable-set.poll` of module instantiation argument ``"
     },
     {
       "type": "module",
-      "line": 140,
-      "filename": "task-builtins.14.wasm",
+      "line": 149,
+      "filename": "task-builtins.15.wasm",
       "module_type": "binary"
     },
     {
       "type": "assert_invalid",
-      "line": 148,
-      "filename": "task-builtins.15.wasm",
+      "line": 157,
+      "filename": "task-builtins.16.wasm",
       "module_type": "binary",
       "text": "type mismatch for export `waitable-set.drop` of module instantiation argument ``"
     },
     {
       "type": "module",
-      "line": 157,
-      "filename": "task-builtins.16.wasm",
+      "line": 166,
+      "filename": "task-builtins.17.wasm",
       "module_type": "binary"
     },
     {
       "type": "assert_invalid",
-      "line": 165,
-      "filename": "task-builtins.17.wasm",
+      "line": 174,
+      "filename": "task-builtins.18.wasm",
       "module_type": "binary",
       "text": "type mismatch for export `waitable.join` of module instantiation argument ``"
     },
     {
       "type": "module",
-      "line": 174,
-      "filename": "task-builtins.18.wasm",
+      "line": 183,
+      "filename": "task-builtins.19.wasm",
       "module_type": "binary"
     },
     {
       "type": "assert_invalid",
-      "line": 184,
-      "filename": "task-builtins.19.wasm",
+      "line": 193,
+      "filename": "task-builtins.20.wasm",
       "module_type": "binary",
       "text": "type mismatch for export `yield` of module instantiation argument ``"
     },
     {
       "type": "module",
-      "line": 195,
-      "filename": "task-builtins.20.wasm",
+      "line": 204,
+      "filename": "task-builtins.21.wasm",
       "module_type": "binary"
     },
     {
       "type": "assert_invalid",
-      "line": 205,
-      "filename": "task-builtins.21.wasm",
+      "line": 214,
+      "filename": "task-builtins.22.wasm",
       "module_type": "binary",
       "text": "type mismatch for export `subtask.drop` of module instantiation argument ``"
     },
     {
       "type": "module",
-      "line": 216,
-      "filename": "task-builtins.22.wasm",
+      "line": 225,
+      "filename": "task-builtins.23.wasm",
       "module_type": "binary"
     },
     {
       "type": "assert_invalid",
-      "line": 226,
-      "filename": "task-builtins.23.wasm",
+      "line": 235,
+      "filename": "task-builtins.24.wasm",
       "module_type": "binary",
       "text": "type mismatch for export `subtask.cancel` of module instantiation argument ``"
     },
     {
       "type": "module",
-      "line": 237,
-      "filename": "task-builtins.24.wasm",
+      "line": 246,
+      "filename": "task-builtins.25.wasm",
       "module_type": "binary"
     },
     {
       "type": "assert_invalid",
-      "line": 260,
-      "filename": "task-builtins.25.wasm",
+      "line": 269,
+      "filename": "task-builtins.26.wasm",
       "module_type": "binary",
       "text": "found:    [] -> [i32]"
     },
     {
       "type": "assert_invalid",
-      "line": 267,
-      "filename": "task-builtins.26.wasm",
+      "line": 276,
+      "filename": "task-builtins.27.wasm",
       "module_type": "binary",
       "text": "found:    [i32] -> []"
     },
     {
       "type": "assert_invalid",
-      "line": 274,
-      "filename": "task-builtins.27.wasm",
+      "line": 283,
+      "filename": "task-builtins.28.wasm",
       "module_type": "binary",
       "text": "immediate larger than two: 100"
     },
     {
       "type": "assert_invalid",
-      "line": 278,
-      "filename": "task-builtins.28.wasm",
+      "line": 287,
+      "filename": "task-builtins.29.wasm",
       "module_type": "binary",
       "text": "immediate larger than two: 100"
     },
     {
       "type": "assert_malformed",
-      "line": 282,
-      "filename": "task-builtins.29.wat",
+      "line": 291,
+      "filename": "task-builtins.30.wat",
       "module_type": "text",
       "text": "expected keyword `i32`"
     },
     {
       "type": "assert_malformed",
-      "line": 286,
-      "filename": "task-builtins.30.wat",
+      "line": 295,
+      "filename": "task-builtins.31.wat",
       "module_type": "text",
       "text": "expected keyword `i32`"
     },
     {
       "type": "assert_malformed",
-      "line": 291,
-      "filename": "task-builtins.31.wasm",
+      "line": 300,
+      "filename": "task-builtins.32.wasm",
       "module_type": "binary",
       "text": "invalid leading byte (0x7e) for context.get"
     },
     {
       "type": "assert_malformed",
-      "line": 298,
-      "filename": "task-builtins.32.wasm",
+      "line": 307,
+      "filename": "task-builtins.33.wasm",
       "module_type": "binary",
       "text": "invalid leading byte (0x7e) for context.set"
     },
     {
       "type": "module",
-      "line": 307,
-      "filename": "task-builtins.33.wasm",
+      "line": 316,
+      "filename": "task-builtins.34.wasm",
       "module_type": "binary"
     }
   ]
diff --git a/tests/snapshots/cli/component-model-async/task-builtins.wast/10.print b/tests/snapshots/cli/component-model-async/task-builtins.wast/11.print
similarity index 100%
rename from tests/snapshots/cli/component-model-async/task-builtins.wast/10.print
rename to tests/snapshots/cli/component-model-async/task-builtins.wast/11.print
diff --git a/tests/snapshots/cli/component-model-async/task-builtins.wast/12.print b/tests/snapshots/cli/component-model-async/task-builtins.wast/13.print
similarity index 100%
rename from tests/snapshots/cli/component-model-async/task-builtins.wast/12.print
rename to tests/snapshots/cli/component-model-async/task-builtins.wast/13.print
diff --git a/tests/snapshots/cli/component-model-async/task-builtins.wast/14.print b/tests/snapshots/cli/component-model-async/task-builtins.wast/15.print
similarity index 100%
rename from tests/snapshots/cli/component-model-async/task-builtins.wast/14.print
rename to tests/snapshots/cli/component-model-async/task-builtins.wast/15.print
diff --git a/tests/snapshots/cli/component-model-async/task-builtins.wast/16.print b/tests/snapshots/cli/component-model-async/task-builtins.wast/17.print
similarity index 100%
rename from tests/snapshots/cli/component-model-async/task-builtins.wast/16.print
rename to tests/snapshots/cli/component-model-async/task-builtins.wast/17.print
diff --git a/tests/snapshots/cli/component-model-async/task-builtins.wast/18.print b/tests/snapshots/cli/component-model-async/task-builtins.wast/19.print
similarity index 100%
rename from tests/snapshots/cli/component-model-async/task-builtins.wast/18.print
rename to tests/snapshots/cli/component-model-async/task-builtins.wast/19.print
diff --git a/tests/snapshots/cli/component-model-async/task-builtins.wast/20.print b/tests/snapshots/cli/component-model-async/task-builtins.wast/21.print
similarity index 100%
rename from tests/snapshots/cli/component-model-async/task-builtins.wast/20.print
rename to tests/snapshots/cli/component-model-async/task-builtins.wast/21.print
diff --git a/tests/snapshots/cli/component-model-async/task-builtins.wast/22.print b/tests/snapshots/cli/component-model-async/task-builtins.wast/23.print
similarity index 100%
rename from tests/snapshots/cli/component-model-async/task-builtins.wast/22.print
rename to tests/snapshots/cli/component-model-async/task-builtins.wast/23.print
diff --git a/tests/snapshots/cli/component-model-async/task-builtins.wast/24.print b/tests/snapshots/cli/component-model-async/task-builtins.wast/25.print
similarity index 100%
rename from tests/snapshots/cli/component-model-async/task-builtins.wast/24.print
rename to tests/snapshots/cli/component-model-async/task-builtins.wast/25.print
diff --git a/tests/snapshots/cli/component-model-async/task-builtins.wast/33.print b/tests/snapshots/cli/component-model-async/task-builtins.wast/33.print
deleted file mode 100644
index 99bfcb71..00000000
--- a/tests/snapshots/cli/component-model-async/task-builtins.wast/33.print
+++ /dev/null
@@ -1,67 +0,0 @@
-(component
-  (core func (;0;) (canon backpressure.set))
-  (core func (;1;) (canon backpressure.set))
-  (core func (;2;) (canon task.return))
-  (core func (;3;) (canon task.return))
-  (core func (;4;) (canon subtask.drop))
-  (core func (;5;) (canon subtask.drop))
-  (core func (;6;) (canon subtask.cancel))
-  (core func (;7;) (canon subtask.cancel))
-  (core func (;8;) (canon subtask.cancel async))
-  (core func (;9;) (canon subtask.cancel async))
-  (core module $m (;0;)
-    (type (;0;) (func (param i32 i32 i32 i32) (result i32)))
-    (memory (;0;) 1)
-    (export "m" (memory 0))
-    (export "r" (func 0))
-    (func (;0;) (type 0) (param i32 i32 i32 i32) (result i32)
-      unreachable
-    )
-  )
-  (core instance $i (;0;) (instantiate $m))
-  (alias core export $i "m" (core memory $m (;0;)))
-  (alias core export $i "r" (core func $r (;10;)))
-  (type $r (;0;) (resource (rep i32)))
-  (core func (;11;) (canon resource.drop $r async))
-  (core func (;12;) (canon resource.drop $r async))
-  (type $s (;1;) (stream))
-  (type $f (;2;) (future))
-  (core func (;13;) (canon future.new $f))
-  (core func (;14;) (canon future.new $f))
-  (core func (;15;) (canon stream.new $s))
-  (core func (;16;) (canon stream.new $s))
-  (core func (;17;) (canon future.cancel-read $f))
-  (core func (;18;) (canon future.cancel-read $f))
-  (core func (;19;) (canon stream.cancel-read $s))
-  (core func (;20;) (canon stream.cancel-read $s))
-  (core func (;21;) (canon future.cancel-write $f))
-  (core func (;22;) (canon future.cancel-write $f))
-  (core func (;23;) (canon stream.cancel-write $s))
-  (core func (;24;) (canon stream.cancel-write $s))
-  (core func (;25;) (canon future.close-readable $f))
-  (core func (;26;) (canon future.close-readable $f))
-  (core func (;27;) (canon future.close-writable $f))
-  (core func (;28;) (canon future.close-writable $f))
-  (core func (;29;) (canon stream.close-readable $s))
-  (core func (;30;) (canon stream.close-readable $s))
-  (core func (;31;) (canon stream.close-writable $s))
-  (core func (;32;) (canon stream.close-writable $s))
-  (core func (;33;) (canon future.read $f (memory $m)))
-  (core func (;34;) (canon future.read $f (memory $m)))
-  (core func (;35;) (canon future.write $f (memory $m)))
-  (core func (;36;) (canon future.write $f (memory $m)))
-  (core func (;37;) (canon stream.read $s (memory $m)))
-  (core func (;38;) (canon stream.read $s (memory $m)))
-  (core func (;39;) (canon stream.write $s (memory $m)))
-  (core func (;40;) (canon stream.write $s (memory $m)))
-  (core func (;41;) (canon error-context.new (memory $m)))
-  (core func (;42;) (canon error-context.new (memory $m)))
-  (core func (;43;) (canon error-context.debug-message (memory $m) (realloc $r)))
-  (core func (;44;) (canon error-context.debug-message (memory $m) (realloc $r)))
-  (core func (;45;) (canon error-context.drop))
-  (core func (;46;) (canon error-context.drop))
-  (core func (;47;) (canon context.get i32 0))
-  (core func (;48;) (canon context.get i32 1))
-  (core func (;49;) (canon context.set i32 0))
-  (core func (;50;) (canon context.set i32 1))
-)
diff --git a/tests/snapshots/cli/component-model-async/task-builtins.wast/34.print b/tests/snapshots/cli/component-model-async/task-builtins.wast/34.print
new file mode 100644
index 00000000..f76142c1
--- /dev/null
+++ b/tests/snapshots/cli/component-model-async/task-builtins.wast/34.print
@@ -0,0 +1,69 @@
+(component
+  (core func (;0;) (canon backpressure.set))
+  (core func (;1;) (canon backpressure.set))
+  (core func (;2;) (canon task.return))
+  (core func (;3;) (canon task.return))
+  (core func (;4;) (canon task.cancel))
+  (core func (;5;) (canon task.cancel))
+  (core func (;6;) (canon subtask.drop))
+  (core func (;7;) (canon subtask.drop))
+  (core func (;8;) (canon subtask.cancel))
+  (core func (;9;) (canon subtask.cancel))
+  (core func (;10;) (canon subtask.cancel async))
+  (core func (;11;) (canon subtask.cancel async))
+  (core module $m (;0;)
+    (type (;0;) (func (param i32 i32 i32 i32) (result i32)))
+    (memory (;0;) 1)
+    (export "m" (memory 0))
+    (export "r" (func 0))
+    (func (;0;) (type 0) (param i32 i32 i32 i32) (result i32)
+      unreachable
+    )
+  )
+  (core instance $i (;0;) (instantiate $m))
+  (alias core export $i "m" (core memory $m (;0;)))
+  (alias core export $i "r" (core func $r (;12;)))
+  (type $r (;0;) (resource (rep i32)))
+  (core func (;13;) (canon resource.drop $r async))
+  (core func (;14;) (canon resource.drop $r async))
+  (type $s (;1;) (stream))
+  (type $f (;2;) (future))
+  (core func (;15;) (canon future.new $f))
+  (core func (;16;) (canon future.new $f))
+  (core func (;17;) (canon stream.new $s))
+  (core func (;18;) (canon stream.new $s))
+  (core func (;19;) (canon future.cancel-read $f))
+  (core func (;20;) (canon future.cancel-read $f))
+  (core func (;21;) (canon stream.cancel-read $s))
+  (core func (;22;) (canon stream.cancel-read $s))
+  (core func (;23;) (canon future.cancel-write $f))
+  (core func (;24;) (canon future.cancel-write $f))
+  (core func (;25;) (canon stream.cancel-write $s))
+  (core func (;26;) (canon stream.cancel-write $s))
+  (core func (;27;) (canon future.close-readable $f))
+  (core func (;28;) (canon future.close-readable $f))
+  (core func (;29;) (canon future.close-writable $f))
+  (core func (;30;) (canon future.close-writable $f))
+  (core func (;31;) (canon stream.close-readable $s))
+  (core func (;32;) (canon stream.close-readable $s))
+  (core func (;33;) (canon stream.close-writable $s))
+  (core func (;34;) (canon stream.close-writable $s))
+  (core func (;35;) (canon future.read $f (memory $m)))
+  (core func (;36;) (canon future.read $f (memory $m)))
+  (core func (;37;) (canon future.write $f (memory $m)))
+  (core func (;38;) (canon future.write $f (memory $m)))
+  (core func (;39;) (canon stream.read $s (memory $m)))
+  (core func (;40;) (canon stream.read $s (memory $m)))
+  (core func (;41;) (canon stream.write $s (memory $m)))
+  (core func (;42;) (canon stream.write $s (memory $m)))
+  (core func (;43;) (canon error-context.new (memory $m)))
+  (core func (;44;) (canon error-context.new (memory $m)))
+  (core func (;45;) (canon error-context.debug-message (memory $m) (realloc $r)))
+  (core func (;46;) (canon error-context.debug-message (memory $m) (realloc $r)))
+  (core func (;47;) (canon error-context.drop))
+  (core func (;48;) (canon error-context.drop))
+  (core func (;49;) (canon context.get i32 0))
+  (core func (;50;) (canon context.get i32 1))
+  (core func (;51;) (canon context.set i32 0))
+  (core func (;52;) (canon context.set i32 1))
+)
diff --git a/tests/snapshots/cli/component-model-async/task-builtins.wast/8.print b/tests/snapshots/cli/component-model-async/task-builtins.wast/8.print
index 967b3b8c..0162fff2 100644
--- a/tests/snapshots/cli/component-model-async/task-builtins.wast/8.print
+++ b/tests/snapshots/cli/component-model-async/task-builtins.wast/8.print
@@ -1,11 +1,11 @@
 (component
   (core module $m (;0;)
-    (type (;0;) (func (result i32)))
-    (import "" "waitable-set.new" (func (;0;) (type 0)))
+    (type (;0;) (func))
+    (import "" "task.cancel" (func $task-cancel (;0;) (type 0)))
   )
-  (core func $waitable-set-new (;0;) (canon waitable-set.new))
+  (core func $task-cancel (;0;) (canon task.cancel))
   (core instance (;0;)
-    (export "waitable-set.new" (func $waitable-set-new))
+    (export "task.cancel" (func $task-cancel))
   )
   (core instance $i (;1;) (instantiate $m
       (with "" (instance 0))
diff --git a/tests/snapshots/cli/component-model-async/task-builtins.wast/9.print b/tests/snapshots/cli/component-model-async/task-builtins.wast/9.print
new file mode 100644
index 00000000..967b3b8c
--- /dev/null
+++ b/tests/snapshots/cli/component-model-async/task-builtins.wast/9.print
@@ -0,0 +1,14 @@
+(component
+  (core module $m (;0;)
+    (type (;0;) (func (result i32)))
+    (import "" "waitable-set.new" (func (;0;) (type 0)))
+  )
+  (core func $waitable-set-new (;0;) (canon waitable-set.new))
+  (core instance (;0;)
+    (export "waitable-set.new" (func $waitable-set-new))
+  )
+  (core instance $i (;1;) (instantiate $m
+      (with "" (instance 0))
+    )
+  )
+)
diff --git a/tests/snapshots/cli/missing-features/component-model/async.wast.json b/tests/snapshots/cli/missing-features/component-model/async.wast.json
index af550650..d65dd165 100644
--- a/tests/snapshots/cli/missing-features/component-model/async.wast.json
+++ b/tests/snapshots/cli/missing-features/component-model/async.wast.json
@@ -34,196 +34,203 @@
       "line": 59,
       "filename": "async.4.wasm",
       "module_type": "binary",
-      "text": "`waitable-set.new` requires the component model async feature"
+      "text": "`task.cancel` requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 65,
+      "line": 71,
       "filename": "async.5.wasm",
       "module_type": "binary",
-      "text": "`waitable-set.wait` requires the component model async feature"
+      "text": "`waitable-set.new` requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 79,
+      "line": 77,
       "filename": "async.6.wasm",
       "module_type": "binary",
-      "text": "`waitable-set.poll` requires the component model async feature"
+      "text": "`waitable-set.wait` requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 93,
+      "line": 91,
       "filename": "async.7.wasm",
       "module_type": "binary",
-      "text": "`waitable-set.drop` requires the component model async feature"
+      "text": "`waitable-set.poll` requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 99,
+      "line": 105,
       "filename": "async.8.wasm",
       "module_type": "binary",
-      "text": "`waitable.join` requires the component model async feature"
+      "text": "`waitable-set.drop` requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 105,
+      "line": 111,
       "filename": "async.9.wasm",
       "module_type": "binary",
-      "text": "`yield` requires the component model async feature"
+      "text": "`waitable.join` requires the component model async feature"
     },
     {
       "type": "assert_invalid",
       "line": 117,
       "filename": "async.10.wasm",
       "module_type": "binary",
-      "text": "`subtask.drop` requires the component model async feature"
+      "text": "`yield` requires the component model async feature"
     },
     {
       "type": "assert_invalid",
       "line": 129,
       "filename": "async.11.wasm",
       "module_type": "binary",
-      "text": "`subtask.cancel` requires the component model async feature"
+      "text": "`subtask.drop` requires the component model async feature"
     },
     {
       "type": "assert_invalid",
       "line": 141,
       "filename": "async.12.wasm",
       "module_type": "binary",
-      "text": "requires the component model async feature"
+      "text": "`subtask.cancel` requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 154,
+      "line": 153,
       "filename": "async.13.wasm",
       "module_type": "binary",
       "text": "requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 169,
+      "line": 166,
       "filename": "async.14.wasm",
       "module_type": "binary",
       "text": "requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 184,
+      "line": 181,
       "filename": "async.15.wasm",
       "module_type": "binary",
       "text": "requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 197,
+      "line": 196,
       "filename": "async.16.wasm",
       "module_type": "binary",
       "text": "requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 210,
+      "line": 209,
       "filename": "async.17.wasm",
       "module_type": "binary",
       "text": "requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 223,
+      "line": 222,
       "filename": "async.18.wasm",
       "module_type": "binary",
       "text": "requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 236,
+      "line": 235,
       "filename": "async.19.wasm",
       "module_type": "binary",
       "text": "requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 249,
+      "line": 248,
       "filename": "async.20.wasm",
       "module_type": "binary",
       "text": "requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 264,
+      "line": 261,
       "filename": "async.21.wasm",
       "module_type": "binary",
       "text": "requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 279,
+      "line": 276,
       "filename": "async.22.wasm",
       "module_type": "binary",
       "text": "requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 292,
+      "line": 291,
       "filename": "async.23.wasm",
       "module_type": "binary",
       "text": "requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 305,
+      "line": 304,
       "filename": "async.24.wasm",
       "module_type": "binary",
       "text": "requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 318,
+      "line": 317,
       "filename": "async.25.wasm",
       "module_type": "binary",
       "text": "requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 331,
+      "line": 330,
       "filename": "async.26.wasm",
       "module_type": "binary",
       "text": "requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 335,
+      "line": 343,
       "filename": "async.27.wasm",
       "module_type": "binary",
       "text": "requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 339,
+      "line": 347,
       "filename": "async.28.wasm",
       "module_type": "binary",
-      "text": "requires the component model async builtins feature"
+      "text": "requires the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 347,
+      "line": 351,
       "filename": "async.29.wasm",
       "module_type": "binary",
-      "text": "require the component model async feature"
+      "text": "requires the component model async builtins feature"
     },
     {
       "type": "assert_invalid",
-      "line": 352,
+      "line": 359,
       "filename": "async.30.wasm",
       "module_type": "binary",
       "text": "require the component model async feature"
     },
     {
       "type": "assert_invalid",
-      "line": 357,
+      "line": 364,
       "filename": "async.31.wasm",
       "module_type": "binary",
       "text": "require the component model async feature"
+    },
+    {
+      "type": "assert_invalid",
+      "line": 369,
+      "filename": "async.32.wasm",
+      "module_type": "binary",
+      "text": "require the component model async feature"
     }
   ]
 }
\ No newline at end of file