Skip to content

insert 路径 stripRuntimeOwnedFields 同样删的是 hook 覆写后的当前值 —— beforeInsert hook 写入的 autonumber 在调用方也提交了同名键时被连坐删除(与其自身文档矛盾) #6339

Description

@baozhoutao

发现于 #5591(update 面同类缺陷)的实测过程,insert 面的对称问题。#5591 的界限明确不含 insert,故独立立单,非其 sub-issue(修法不在 #5591 的完成范围内,也不依赖它先合)。

现象

stripRuntimeOwnedFields(packages/objectql/src/validation/rule-validator.ts)与 update 面的 stripReadonlyFields 用的是同一种判据:suppliedKeys 只是键名集合。而 engine.ts insert 路径上:

  • triggerHooks('beforeInsert', rowCtx)engine.ts:5318
  • rowsrowHookContextsinput.data 映射而来,在 engine.ts:5341
  • suppliedPerRow 快照在 engine.ts:5374
  • 剥离在 engine.ts:5397-5412,delete result[name] 删的是执行到剥离时的当前值

于是 hook 若覆写了一个调用方也提交过的 runtime-owned 键,被删掉的是 hook 的写入,而不是调用方提交的值。

实测(worktree @ origin/main cca11e9d3,真 ObjectQL + InMemory 驱动)

对象 probe_num2 { title: text, code: autonumber }
beforeInsert hook: ctx.input.data.code = 'HOOK-OVERWRITE'

A) 调用方不提交 code                => 落库 code = "HOOK-1"     (hook 写入存活,符合文档)
B) 调用方提交 code='CALLER-FORGED'  => 落库 code = "1"          (hook 写入被删,序列补发)

B 与该函数自己的文档直接矛盾 —— runtimeOwnedStripWarning() 的正文写着:

A beforeInsert/beforeUpdate hook does NOT need either — hook-written keys are not caller-supplied.

A 与 B 的差别只有「调用方 payload 里是否碰巧出现同名键」,与 #5591 在 update 面记录的是同一条判据错误。

影响

窄但真实:一个在 beforeInsert 里重新签发/归一化记录号的 hook,只要调用方同时提交了该键,其写入就被静默丢弃并回落到序列值。整记录 POST(读模板 → 改字段 → 整体提交)会触发。今日无已知线上用例,故未自评严重度,交分诊定级。

期望

#5591 同一判据:剥离作用于调用方提交的值,不作用于 hook 覆写后的当前值。#5591 在 update 面的修法(入口快照携带调用方的值,剥离时以 Object.is 比对身份;非导出函数,签名可自由收敛)可直接照搬到 stripRuntimeOwnedFields + engine.tssuppliedPerRow

注意 insert 面有一处 update 面没有的细节需先确认:suppliedPerRow 取自 opCtx.data,而 hook 是原地ctx.input.data;两者是否同一引用决定了快照是否必须显式浅拷贝(update 面 #5591 已因此显式 spread)。上面的 A 用例说明 hook 新增的键当前不在快照里,所以至少新增面是干净的。

边界


Blocked-by: #5591


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions