Vue 3.5.42 的 switch 内 await 报 object is not iterable,检查生成代码的分号
Vue 3.5.42 在 switch case 内改写顶层 await 时可能漏掉前导分号,连接前一条表达式。检查产物、局部分号与3.5.43正式修复。
<script setup> 中同样的调用放在普通代码块里正常,移进 switch case 后却在组件初始化时报 TypeError: object is not iterable,可以检查编译产物是否把前一条调用与 await 转换表达式连在了一起。
这条具体编译回归在 Vue 3.5.42确认,已在3.5.43修复。适用条件是 case 分支里的顶层 await 前面还有表达式语句;不能仅凭 object is not iterable 就认定是Vue版本问题,真实解构非可迭代对象仍是另一条常见原因。
原代码的 await,在产物中变成了括号表达式
下面是说明触发结构的组件片段:
<script setup>
const mode = 1;
function prepare() {}
async function loadValue() { return 42; }
switch (mode) {
case 1:
prepare()
await loadValue()
break;
}
</script>
Vue会把 <script setup> 的顶层 await 编译为异步 setup,并用 withAsyncContext 保存组件上下文。即使 await 位于 switch 里面,只要没有进入另一个函数,仍属于这里的顶层转换。
受影响产物在 prepare() 后直接接一个以 ( 开始的包装表达式。JavaScript的自动分号插入不会简单地按换行拆开它们,于是两条独立语句被连成一次调用表达式。随后报错的位置可能落在转换生成的解构或调用中,离源码里的await并不直观。
先查报错对应的生成代码,观察前一行末尾和 _withAsyncContext 包装前是否缺少分隔。不要直接改生成变量名、移除包装,或让加载函数返回数组来迎合错误的解构;包装中的状态管理本来是编译器的职责。
暂时为前一条语句明确加分号
无法立即更新编译器时,可以在相应 case 中结束前一条表达式:
switch (mode) {
case 1:
prepare();
await loadValue();
break;
}
这是对同一片段的局部修改,保留原来的执行顺序。不要把 await 整段移到 onMounted 只为绕开报错:那会把组件初始化阶段的等待变成挂载后的异步工作,可能改变首屏和服务端渲染结果。
多个连续 await 也应逐条查看分隔关系。单独给 await 后面补分号,未必能分开它前面那条调用,关键仍是实际产物中的语句边界。
修复落在 compiler-sfc,需要核对实际依赖
Vue 3.5.43于2026年9月17日发布,正式源码增加了对 SwitchCase 语句列表的跟踪,使这类 await 包装得到需要的前导分号。修复同时覆盖直接switch和嵌套在普通块内的switch。
检查项目实际使用的 vue、@vue/compiler-sfc 及负责SFC转换的插件,不要只看package.json的范围。工作区、框架或插件仍解析到3.5.42编译器时,运行时包升级并不能自动改好已经生成的JavaScript。框架管理的依赖按框架支持方式更新,自主管理的项目则保持Vue与编译器版本一致。
组件采用异步 setup 时,还要保留项目原来正确的 Suspense 边界;修复分号不会取消这项运行条件。验收从原构建入口生成代码,确认两个表达式分开,再检查组件能进入预期分支、等待加载结束并正常渲染。如果实际安装版本已经包含修复、产物边界也正确,应回到真正被解构的值与调用返回值继续查。


