DEBUG.WIKI
搬瓦工;先看线路,再选 VPS;CN2 GIA · 对应线路套餐;查看线路 →
野草云;香港 200Mbps 峰值;不限月流量 · BGP VPS;查看套餐 →
RackNerd;$21.99/年 · 1GB KVM

Svelte 的 select 后加文本就编译失败:静态 value 生成了错误 AST

Svelte 5.56.3 的 select 带静态 value 且后有兄弟节点时,可能在 esrap 输出阶段报 null.type。核对 5.57.0 修复并保留表单语义。

同一个组件,<select> 单独放着还能处理,后面加一段文本或兄弟元素,Vite 就报 Cannot read properties of null (reading 'type')。栈落在 esrap 的 MemberExpression,并标记 vite-plugin-svelte:compile 时,可以检查 Svelte 对静态 value 属性的处理。

这一回归在 Svelte 5.56.3 有明确触发结构,5.57.0 正式版已经修复。错误并不限于没有 option 的空 select;有子选项时也能出现,不能把“给它补一个 option”当作修复。

两行合法模板就可能触发

最短的结构如下,只用于说明失败条件:

<select value="foo"></select>
foo

这里 select 的 value 是静态属性,后面还有一个文本节点。浏览器尚未运行组件,编译器生成 JavaScript 的阶段就失败了。因此,给页面加 onMount、延迟读取 DOM,或者在浏览器里查哪个业务对象为 null,都可能查错阶段。

先保留完整编译栈、Svelte 实际版本和失败模板。若栈是在应用运行后读取某个对象的 type,没有 esrap 或组件编译入口,就应回到那个实际对象排查,不能仅按相同错误文本套用本篇。

静态元素优化漏掉了 select 的特殊处理

Svelte 对部分静态元素可以采用简化的生成路径。但表单控件的 value、checked 与普通静态属性不同,需要保留相应处理。

受影响实现对 input 和 textarea 排除了这条静态路径,却没有同样处理 select。带静态 value 的 select 与兄弟节点组合时,后续转换可能构造出 object 为空的成员访问节点,交给 esrap 输出时才暴露异常。

Svelte 5.57.0 的正式实现把 select 加入这项判断,使它不再按这里的普通静态元素处理。修复针对生成的 AST,不需要开发者去给 esrap 的空对象随意补默认值。

更新后保留真实表单行为检查

在项目支持范围内更新到包含修复的 Svelte 版本,保存原锁文件,确认构建实际解析到的新编译器。修改 node_modules 中的编译器或生成代码很容易在重装、CI 构建时消失,不适合作为正式维护方式。

不要为了绕过报错就将每个静态 value 改成 bind:value。后者引入双向状态关系,会改变组件数据流;也不应直接删掉 select 后面的业务内容。必须临时调整结构时,应限定在这个组件,并对照原来的默认选中值、用户选择和提交结果。

重新走原构建入口,确认带文本、带兄弟元素的实际模板都能生成产物。随后在浏览器检查真正的选项列表、初始值和选择变化;编译通过不能证明表单含义仍然相同。若组件还有服务端渲染,再检查首次页面与客户端接管后的选择状态一致。

这条修复不会替应用补齐缺失选项。value="foo" 与实际 option 是否对应,仍是应用需要正确表达的关系,应与编译器崩溃分开检查。