Repository: bytecodealliance/wasm-tools
Pull request #2150 (2025-04-16 18:35:02)

Only allow one async context slot
Update for WebAssembly/component-model#501


Patch:
diff --git a/crates/wasmparser/src/validator/component.rs b/crates/wasmparser/src/validator/component.rs
index 233b3eb0..981f409f 100644
--- a/crates/wasmparser/src/validator/component.rs
+++ b/crates/wasmparser/src/validator/component.rs
@@ -1231,8 +1231,8 @@ impl ComponentState {
                 "`context.get` requires the component model async feature"
             )
         }
-        if i > 2 {
-            bail!(offset, "`context.get` immediate larger than two: {i}")
+        if i > 0 {
+            bail!(offset, "`context.get` immediate must be zero: {i}")
         }
 
         self.core_funcs
@@ -1247,8 +1247,8 @@ impl ComponentState {
                 "`context.set` requires the component model async feature"
             )
         }
-        if i > 2 {
-            bail!(offset, "`context.set` immediate larger than two: {i}")
+        if i > 0 {
+            bail!(offset, "`context.set` immediate must be zero: {i}")
         }
 
         self.core_funcs
diff --git a/crates/wit-component/src/dummy.rs b/crates/wit-component/src/dummy.rs
index a18b39bd..003bed34 100644
--- a/crates/wit-component/src/dummy.rs
+++ b/crates/wit-component/src/dummy.rs
@@ -390,9 +390,7 @@ fn push_root_async_intrinsics(dst: &mut String) {
 (import "$root" "[error-context-debug-message-latin1+utf16]" (func (param i32 i32)))
 (import "$root" "[error-context-drop]" (func (param i32)))
 (import "$root" "[context-get-0]" (func (result i32)))
-(import "$root" "[context-get-1]" (func (result i32)))
 (import "$root" "[context-set-0]" (func (param i32)))
-(import "$root" "[context-set-1]" (func (param i32)))
 
 ;; deferred behind 🚝 or 🚟 upstream
 ;;(import "$root" "[async-lower][waitable-set-wait]" (func (param i32 i32) (result i32)))


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 05fa5119..ff4caf87 100644
--- a/crates/wit-component/tests/components/async-builtins/component.wat
+++ b/crates/wit-component/tests/components/async-builtins/component.wat
@@ -27,21 +27,19 @@
     (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)))
+    (import "$root" "[context-set-0]" (func (;20;) (type 0)))
     (memory (;0;) 1)
-    (export "[async-lift-stackful]foo" (func 23))
-    (export "[async-lift-stackful]foo:foo/bar#foo" (func 24))
+    (export "[async-lift-stackful]foo" (func 21))
+    (export "[async-lift-stackful]foo:foo/bar#foo" (func 22))
     (export "memory" (memory 0))
-    (export "cabi_realloc" (func 25))
-    (func (;23;) (type 2) (param i32 i32)
+    (export "cabi_realloc" (func 23))
+    (func (;21;) (type 2) (param i32 i32)
       unreachable
     )
-    (func (;24;) (type 2) (param i32 i32)
+    (func (;22;) (type 2) (param i32 i32)
       unreachable
     )
-    (func (;25;) (type 6) (param i32 i32 i32 i32) (result i32)
+    (func (;23;) (type 6) (param i32 i32 i32 i32) (result i32)
       unreachable
     )
     (@producers
@@ -167,9 +165,7 @@
   (alias core export 0 "7" (core func (;14;)))
   (core func (;15;) (canon error-context.drop))
   (core func (;16;) (canon context.get i32 0))
-  (core func (;17;) (canon context.get i32 1))
-  (core func (;18;) (canon context.set i32 0))
-  (core func (;19;) (canon context.set i32 1))
+  (core func (;17;) (canon context.set i32 0))
   (core instance (;1;)
     (export "[backpressure-set]" (func 0))
     (export "[waitable-set-new]" (func 1))
@@ -188,19 +184,17 @@
     (export "[error-context-debug-message-latin1+utf16]" (func 14))
     (export "[error-context-drop]" (func 15))
     (export "[context-get-0]" (func 16))
-    (export "[context-get-1]" (func 17))
-    (export "[context-set-0]" (func 18))
-    (export "[context-set-1]" (func 19))
+    (export "[context-set-0]" (func 17))
   )
-  (core func (;20;) (canon task.cancel))
-  (alias core export 0 "8" (core func (;21;)))
+  (core func (;18;) (canon task.cancel))
+  (alias core export 0 "8" (core func (;19;)))
   (core instance (;2;)
-    (export "[task-cancel]" (func 20))
-    (export "[task-return]foo" (func 21))
+    (export "[task-cancel]" (func 18))
+    (export "[task-return]foo" (func 19))
   )
-  (alias core export 0 "9" (core func (;22;)))
+  (alias core export 0 "9" (core func (;20;)))
   (core instance (;3;)
-    (export "[task-return]foo" (func 22))
+    (export "[task-return]foo" (func 20))
   )
   (core instance (;4;) (instantiate 0
       (with "$root" (instance 1))
@@ -210,41 +204,41 @@
   )
   (alias core export 4 "memory" (core memory (;0;)))
   (alias core export 0 "$imports" (core table (;0;)))
-  (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 func (;21;) (canon waitable-set.wait (memory 0)))
+  (core func (;22;) (canon waitable-set.poll (memory 0)))
+  (core func (;23;) (canon error-context.new (memory 0) string-encoding=utf8))
+  (core func (;24;) (canon error-context.new (memory 0) string-encoding=utf16))
+  (core func (;25;) (canon error-context.new (memory 0) string-encoding=latin1+utf16))
+  (alias core export 4 "cabi_realloc" (core func (;26;)))
+  (core func (;27;) (canon error-context.debug-message (memory 0) (realloc 26) string-encoding=utf8))
+  (core func (;28;) (canon error-context.debug-message (memory 0) (realloc 26) string-encoding=utf16))
+  (core func (;29;) (canon error-context.debug-message (memory 0) (realloc 26) string-encoding=latin1+utf16))
+  (core func (;30;) (canon task.return (result string) (memory 0) string-encoding=utf8))
+  (core func (;31;) (canon task.return (result string) (memory 0) string-encoding=utf8))
   (core instance (;5;)
     (export "$imports" (table 0))
-    (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))
+    (export "0" (func 21))
+    (export "1" (func 22))
+    (export "2" (func 23))
+    (export "3" (func 24))
+    (export "4" (func 25))
+    (export "5" (func 27))
+    (export "6" (func 28))
+    (export "7" (func 29))
+    (export "8" (func 30))
+    (export "9" (func 31))
   )
   (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 (;34;)))
-  (func (;0;) (type 0) (canon lift (core func 34) (memory 0) (realloc 28) string-encoding=utf8 async))
+  (alias core export 4 "[async-lift-stackful]foo" (core func (;32;)))
+  (func (;0;) (type 0) (canon lift (core func 32) (memory 0) (realloc 26) 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 (;35;)))
-  (func (;2;) (type 1) (canon lift (core func 35) (memory 0) (realloc 28) string-encoding=utf8 async))
+  (alias core export 4 "[async-lift-stackful]foo:foo/bar#foo" (core func (;33;)))
+  (func (;2;) (type 1) (canon lift (core func 33) (memory 0) (realloc 26) 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 d76d09a0..ba3fadc7 100644
--- a/crates/wit-component/tests/components/async-builtins/module.wat
+++ b/crates/wit-component/tests/components/async-builtins/module.wat
@@ -19,9 +19,7 @@
   (import "$root" "[error-context-debug-message-latin1+utf16]" (func (param i32 i32)))
   (import "$root" "[error-context-drop]" (func (param i32)))
   (import "$root" "[context-get-0]" (func (result i32)))
-  (import "$root" "[context-get-1]" (func (result i32)))
   (import "$root" "[context-set-0]" (func (param i32)))
-  (import "$root" "[context-set-1]" (func (param i32)))
   (func (export "[async-lift-stackful]foo") (param i32 i32) unreachable)
   (func (export "[async-lift-stackful]foo:foo/bar#foo") (param i32 i32) unreachable)
   (memory (export "memory") 1)
diff --git a/tests/cli/component-model-async/task-builtins.wast b/tests/cli/component-model-async/task-builtins.wast
index 97616ad1..f1bca5d9 100644
--- a/tests/cli/component-model-async/task-builtins.wast
+++ b/tests/cli/component-model-async/task-builtins.wast
@@ -245,22 +245,16 @@
 ;; context.{get,set}
 (component
   (core func $get0 (canon context.get i32 0))
-  (core func $get1 (canon context.get i32 1))
   (core func $set0 (canon context.set i32 0))
-  (core func $set1 (canon context.set i32 1))
 
   (core module $m
     (import "" "get0" (func (result i32)))
-    (import "" "get1" (func (result i32)))
     (import "" "set0" (func (param i32)))
-    (import "" "set1" (func (param i32)))
   )
   (core instance (instantiate $m
     (with "" (instance
       (export "get0" (func $get0))
-      (export "get1" (func $get1))
       (export "set0" (func $set0))
-      (export "set1" (func $set1))
     ))
   ))
 )
@@ -279,14 +273,22 @@
     (core instance $i (instantiate $m (with "" (instance (export "" (func $f))))))
   )
   "found:    [i32] -> []")
+(assert_invalid
+  (component
+    (core func (canon context.get i32 1)))
+  "immediate must be zero: 1")
+(assert_invalid
+  (component
+    (core func (canon context.set i32 1)))
+  "immediate must be zero: 1")
 (assert_invalid
   (component
     (core func (canon context.get i32 100)))
-  "immediate larger than two: 100")
+  "immediate must be zero: 100")
 (assert_invalid
   (component
     (core func (canon context.set i32 100)))
-  "immediate larger than two: 100")
+  "immediate must be zero: 100")
 (assert_malformed
   (component quote
     "(core func (canon context.get i64 100))")
@@ -378,8 +380,8 @@
   (canon error-context.drop (core func))
 
   (core func (canon context.get i32 0))
-  (canon context.get i32 1 (core func))
+  (canon context.get i32 0 (core func))
 
   (core func (canon context.set i32 0))
-  (canon context.set i32 1 (core func))
+  (canon context.set i32 0 (core func))
 )
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 17c33219..7f9ba4c3 100644
--- a/tests/snapshots/cli/component-model-async/task-builtins.wast.json
+++ b/tests/snapshots/cli/component-model-async/task-builtins.wast.json
@@ -172,64 +172,78 @@
     },
     {
       "type": "assert_invalid",
-      "line": 269,
+      "line": 263,
       "filename": "task-builtins.26.wasm",
       "module_type": "binary",
       "text": "found:    [] -> [i32]"
     },
     {
       "type": "assert_invalid",
-      "line": 276,
+      "line": 270,
       "filename": "task-builtins.27.wasm",
       "module_type": "binary",
       "text": "found:    [i32] -> []"
     },
     {
       "type": "assert_invalid",
-      "line": 283,
+      "line": 277,
       "filename": "task-builtins.28.wasm",
       "module_type": "binary",
-      "text": "immediate larger than two: 100"
+      "text": "immediate must be zero: 1"
     },
     {
       "type": "assert_invalid",
-      "line": 287,
+      "line": 281,
       "filename": "task-builtins.29.wasm",
       "module_type": "binary",
-      "text": "immediate larger than two: 100"
+      "text": "immediate must be zero: 1"
+    },
+    {
+      "type": "assert_invalid",
+      "line": 285,
+      "filename": "task-builtins.30.wasm",
+      "module_type": "binary",
+      "text": "immediate must be zero: 100"
+    },
+    {
+      "type": "assert_invalid",
+      "line": 289,
+      "filename": "task-builtins.31.wasm",
+      "module_type": "binary",
+      "text": "immediate must be zero: 100"
     },
     {
       "type": "assert_malformed",
-      "line": 291,
-      "filename": "task-builtins.30.wat",
+      "line": 293,
+      "filename": "task-builtins.32.wat",
       "module_type": "text",
       "text": "expected keyword `i32`"
     },
     {
       "type": "assert_malformed",
-      "line": 295,
-      "filename": "task-builtins.31.wat",
+      "line": 297,
+      "filename": "task-builtins.33.wat",
       "module_type": "text",
       "text": "expected keyword `i32`"
     },
     {
       "type": "assert_malformed",
-      "line": 300,
-      "filename": "task-builtins.32.wasm",
+      "line": 302,
+      "filename": "task-builtins.34.wasm",
       "module_type": "binary",
       "text": "invalid leading byte (0x7e) for context.get"
     },
     {
       "type": "assert_malformed",
-      "line": 307,
-      "filename": "task-builtins.33.wasm",
+      "line": 309,
+      "filename": "task-builtins.35.wasm",
       "module_type": "binary",
       "text": "invalid leading byte (0x7e) for context.set"
     },
     {
       "type": "module",
-      "line": 316,
-      "filename": "task-builtins.34.wasm",
+      "line": 318,
+      "filename": "task-builtins.36.wasm",
       "module_type": "binary"
     }
   ]
diff --git a/tests/snapshots/cli/component-model-async/task-builtins.wast/25.print b/tests/snapshots/cli/component-model-async/task-builtins.wast/25.print
index 0bacf89e..37470d88 100644
--- a/tests/snapshots/cli/component-model-async/task-builtins.wast/25.print
+++ b/tests/snapshots/cli/component-model-async/task-builtins.wast/25.print
@@ -1,21 +1,15 @@
 (component
   (core func $get0 (;0;) (canon context.get i32 0))
-  (core func $get1 (;1;) (canon context.get i32 1))
-  (core func $set0 (;2;) (canon context.set i32 0))
-  (core func $set1 (;3;) (canon context.set i32 1))
+  (core func $set0 (;1;) (canon context.set i32 0))
   (core module $m (;0;)
     (type (;0;) (func (result i32)))
     (type (;1;) (func (param i32)))
     (import "" "get0" (func (;0;) (type 0)))
-    (import "" "get1" (func (;1;) (type 0)))
-    (import "" "set0" (func (;2;) (type 1)))
-    (import "" "set1" (func (;3;) (type 1)))
+    (import "" "set0" (func (;1;) (type 1)))
   )
   (core instance (;0;)
     (export "get0" (func $get0))
-    (export "get1" (func $get1))
     (export "set0" (func $set0))
-    (export "set1" (func $set1))
   )
   (core instance (;1;) (instantiate $m
       (with "" (instance 0))
diff --git a/tests/snapshots/cli/component-model-async/task-builtins.wast/34.print b/tests/snapshots/cli/component-model-async/task-builtins.wast/36.print
similarity index 97%
rename from tests/snapshots/cli/component-model-async/task-builtins.wast/34.print
rename to tests/snapshots/cli/component-model-async/task-builtins.wast/36.print
index f76142c1..498add71 100644
--- a/tests/snapshots/cli/component-model-async/task-builtins.wast/34.print
+++ b/tests/snapshots/cli/component-model-async/task-builtins.wast/36.print
@@ -63,7 +63,7 @@
   (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 (;50;) (canon context.get i32 0))
   (core func (;51;) (canon context.set i32 0))
-  (core func (;52;) (canon context.set i32 1))
+  (core func (;52;) (canon context.set i32 0))
 )