perf(commands): skip no-op dispatch emissions
This commit is contained in:
@@ -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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user