拒绝不是二元组的树偏移输入

src/features/ui-editor/stateTransition.ts 的 set-tree-offset 分支增加 min.length !== 2 判据:空数组会让 every 空真通过,缺坐标时 max 会算出 NaN 污染渲染消费的偏移
tests/uiEditorState.test.ts 补「[12] 与 [] 都判 invalid」用例
This commit is contained in:
2026-09-24 16:00:13 +08:00
parent a871684bd7
commit e2e9243415
2 changed files with 19 additions and 1 deletions
@@ -93,7 +93,8 @@ export function applyUiEditorCommand(
if (!tree) return { ok: false, reason: 'missing' };
if (command.type === 'set-tree-offset') {
if (!command.min.every(Number.isFinite))
// 只校验元素有限不够:`[]` 会让 every 空真通过,缺第二个坐标时 max 会算出 NaN。
if (command.min.length !== 2 || !command.min.every(Number.isFinite))
return { ok: false, reason: 'invalid' };
const size = imageLogicalSize(next, command.treeId);
if (!size) return { ok: false, reason: 'invalid' };
@@ -138,6 +138,23 @@ describe('useUiEditorState', () => {
}
});
it('rejects a tree offset that is not a two-element tuple', () => {
const state: State = {
...structuredClone(EMPTY_UI_EDITOR_STATE),
ui_design_images: { page: image('Page') },
ui_trees: [{ src_ui_design: 'page', root: pageRoot('root') }],
};
for (const min of [[12], []] as unknown as [number, number][]) {
expect(
applyUiEditorCommand(state, {
type: 'set-tree-offset',
treeId: 'page',
min,
}),
).toEqual({ ok: false, reason: 'invalid' });
}
});
it('reports persistable state invariant failures before save', () => {
const state = structuredClone(EMPTY_UI_EDITOR_STATE);
state.ui_trees = [{ src_ui_design: 'missing', root: pageRoot('root') }];