Fix
diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp
index a948f25..339753a 100644
--- a/src/tools/wasm-ctor-eval.cpp
+++ b/src/tools/wasm-ctor-eval.cpp
@@ -890,11 +890,11 @@
              value.type.getHeapType().isMaybeShared(HeapType::i31));
     }
 
-    // GC data (structs and arrays) must be handled with the special global-
-    // creating logic later down. But MVP types as well as i31s (even
-    // externalized i31s) can be handled by the general makeConstantExpression
-    // logic (which knows how to handle externalization, for i31s; and it also
-    // can handle string constants).
+    // GC data (structs, arrays, and waitqueues) must be handled with the
+    // special global- creating logic later down. But MVP types as well as i31s
+    // (even externalized i31s) can be handled by the general
+    // makeConstantExpression logic (which knows how to handle externalization,
+    // for i31s; and it also can handle string constants).
     if (!value.isData() || value.isString()) {
       return builder.makeConstantExpression(original);
     }
@@ -956,6 +956,8 @@
       } else if (heapType.isArray()) {
         // TODO: for repeated identical values, can use ArrayNew
         init = builder.makeArrayNewFixed(heapType, args);
+      } else if (heapType == HeapTypes::sharedWaitqueue) {
+        init = builder.makeWaitqueueNew();
       } else {
         WASM_UNREACHABLE("bad gc type");
       }
diff --git a/src/wasm-type.h b/src/wasm-type.h
index 96fb08d..7a8d5da 100644
--- a/src/wasm-type.h
+++ b/src/wasm-type.h
@@ -1194,8 +1194,8 @@
 
 inline bool HeapType::isData() const {
   auto kind = getKind();
-  return isMaybeShared(string) || kind == HeapTypeKind::Struct ||
-         kind == HeapTypeKind::Array;
+  return isMaybeShared(string) || isMaybeShared(waitqueue) ||
+         kind == HeapTypeKind::Struct || kind == HeapTypeKind::Array;
 }
 
 inline bool HeapType::isSignature() const {
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index 272cc5a..d8b14c2 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -73,6 +73,9 @@
 
   if (type.isRef() && type.getHeapType().isMaybeShared(HeapType::waitqueue)) {
     assert(type.isNonNullable());
+    // See ~Literal and isData(). isData() is true for waitqueues so we expect
+    // gcData to be present even if null.
+    new (&gcData) std::shared_ptr<GCData>();
     return;
   }
 
@@ -113,7 +116,6 @@
   assert((isData() && gcData) ||
          (type.isMaybeShared(HeapType::ext) && gcData) ||
          (type.isMaybeShared(HeapType::string) && gcData) ||
-         (type.isMaybeShared(HeapType::waitqueue) && gcData) ||
          (type.isMaybeShared(HeapType::any) && gcData) ||
          (type.isBottom() && !gcData));
 }
@@ -189,7 +191,6 @@
       return;
     case HeapType::ext:
     case HeapType::any:
-    case HeapType::waitqueue:
       // Externalized or internalized reference/payload.
       new (&gcData) std::shared_ptr<GCData>(other.gcData);
       return;
@@ -205,6 +206,7 @@
     case HeapType::cont:
     case HeapType::struct_:
     case HeapType::array:
+    case HeapType::waitqueue:
       WASM_UNREACHABLE("invalid type");
     case HeapType::string:
       WASM_UNREACHABLE("TODO: string literals");
@@ -371,10 +373,8 @@
 }
 
 std::shared_ptr<GCData> Literal::getGCData() const {
-  assert(
-    isNull() || isData() ||
-    (type.isRef() && (type.getHeapType().isMaybeShared(HeapType::ext) ||
-                      type.getHeapType().isMaybeShared(HeapType::waitqueue))));
+  assert(isNull() || isData() ||
+         (type.isRef() && (type.getHeapType().isMaybeShared(HeapType::ext))));
   return gcData;
 }