perf(commands): skip no-op dispatch emissions

This commit is contained in:
syntaxbullet
2026-07-04 15:21:41 +02:00
parent 7188569672
commit d9e5e05183
2 changed files with 29 additions and 0 deletions

View File

@@ -1,10 +1,17 @@
import { describe, expect, test } from "bun:test"; import { describe, expect, test } from "bun:test";
import type { Command } from "./command";
import { createInitialAppState } from "@editor/initial-state"; import { createInitialAppState } from "@editor/initial-state";
import { createAppStore } from "@editor/store"; import { createAppStore } from "@editor/store";
import { commandIds } from "./ids"; import { commandIds } from "./ids";
import { createCommandRegistry } from "./registry"; import { createCommandRegistry } from "./registry";
import { viewportPanCommand } from "./viewport"; import { viewportPanCommand } from "./viewport";
const noOpCommand: Command<unknown> = {
id: "test.noop",
name: "No-op",
execute: ({ state }) => state,
};
describe("command dispatcher", () => { describe("command dispatcher", () => {
test("throws for unknown commands", () => { test("throws for unknown commands", () => {
const store = createAppStore(createInitialAppState("Test"), createCommandRegistry([])); const store = createAppStore(createInitialAppState("Test"), createCommandRegistry([]));
@@ -16,4 +23,23 @@ describe("command dispatcher", () => {
store.dispatch(commandIds.viewportPan, { delta: { x: 3, y: 7 } }); store.dispatch(commandIds.viewportPan, { delta: { x: 3, y: 7 } });
expect(store.getState().editor.viewport.center).toEqual({ x: 3, y: 7 }); expect(store.getState().editor.viewport.center).toEqual({ x: 3, y: 7 });
}); });
test("repeated no-op commands do not emit or record history", () => {
const initialState = createInitialAppState("Test");
const store = createAppStore(initialState, createCommandRegistry([noOpCommand]));
let notificationCount = 0;
store.subscribe(() => {
notificationCount += 1;
});
const firstResult = store.dispatch("test.noop" as never, undefined as never);
const secondResult = store.dispatch("test.noop" as never, undefined as never);
expect(firstResult).toBe(initialState);
expect(secondResult).toBe(initialState);
expect(store.getState()).toBe(initialState);
expect(store.getState().history.past).toHaveLength(0);
expect(store.getState().history.future).toHaveLength(0);
expect(notificationCount).toBe(0);
});
}); });

View File

@@ -25,6 +25,9 @@ export function createCommandDispatcher(options: {
const currentState = options.getState(); const currentState = options.getState();
const context: CommandContext = { state: currentState }; const context: CommandContext = { state: currentState };
const executedState = command.execute(context, payload); const executedState = command.execute(context, payload);
if (executedState === currentState) {
return currentState;
}
const nextState = shouldRecordHistory(commandId, currentState, executedState) ? recordHistory(currentState, executedState) : executedState; const nextState = shouldRecordHistory(commandId, currentState, executedState) ? recordHistory(currentState, executedState) : executedState;
options.setState(nextState); options.setState(nextState);
return nextState; return nextState;