fix(07-03): #06-04-3 shift param indexes from the command index on delete

- Add a private getParamRange helper using paramUsed as the last-step sentinel
- Roll back indexArray from the command index instead of the param byte offset
- Un-skip the middle-step delete cases
This commit is contained in:
unanmed 2026-09-15 18:45:31 +08:00
parent 965e002476
commit 45dde1cb1c
2 changed files with 29 additions and 7 deletions

View File

@ -207,8 +207,8 @@ describe('ReplayArray single operations', () => {
expect(array.get(1)).toEqual({ command: 3, params: [30], index: 1 });
});
// 疑似 bugdelete 中间步骤后索引数组未按删除位置回退,导致后续步骤读到错误参数,详见 06-TEST-FINDINGS.md #06-04-3修复后取消 skip
it.skip('deletes a middle step and shifts later param indexes', () => {
// 验证 delete 中间步骤后索引数组按删除位置回退,后续步骤仍读到正确参数
it('deletes a middle step and shifts later param indexes', () => {
const array = createArray();
array.add(1, [10]);
array.add(2, [20]);
@ -567,8 +567,8 @@ describe('ReplayArray stream and buffer combination', () => {
expect(stream.read()).toEqual({ command: 3, params: [30], index: 3 });
});
// 疑似 bugdelete 中间步后索引数组未按删除位置回退,异质序列后续步骤读到错误参数,详见 06-TEST-FINDINGS.md #06-04-3修复后取消 skip
it.skip('reads the new order after deleting a middle step from a heterogeneous route', () => {
// 验证异质序列删除中间步后索引按删除位置回退,读流按新次序精确读回
it('reads the new order after deleting a middle step from a heterogeneous route', () => {
const array = createHeterogeneousArray();
array.delete(1);

View File

@ -46,6 +46,13 @@ interface IDecodedCommand {
readonly paramCount: number;
}
interface IParamRange {
/** 命令参数在参数缓冲区中的起始字节 */
readonly start: number;
/** 命令参数在参数缓冲区中的结束字节,不包含该字节 */
readonly end: number;
}
export class ReplayArray implements IReplayArray {
length: number = 0;
commandWidth: ReplayCommandWidth = ReplayCommandWidth.Uint8;
@ -393,6 +400,20 @@ export class ReplayArray implements IReplayArray {
});
}
/**
*
* @param index
*/
private getParamRange(index: number): IParamRange {
const start = this.indexArray[index];
const end =
index + 1 < this.length
? this.indexArray[index + 1]
: this.paramUsed;
return { start, end };
}
add(command: number, params: ReplayParamValue[]): void {
if (this.disabled > 0) return;
const normalized = this.normalizeParamList(params);
@ -447,8 +468,9 @@ export class ReplayArray implements IReplayArray {
if (this.disabled > 0) return;
const commandSize = this.getCommandSize();
const commandStart = index * commandSize;
const paramStart = this.indexArray[index];
const nextParam = this.indexArray[index + 1];
const range = this.getParamRange(index);
const paramStart = range.start;
const nextParam = range.end;
const paramLength = nextParam - paramStart;
// 直接进行位移
@ -470,7 +492,7 @@ export class ReplayArray implements IReplayArray {
}
// 最后把后面的索引减少 paramLength
for (let i = paramStart; i < this.length; i++) {
for (let i = index; i < this.length; i++) {
this.indexArray[i] -= paramLength;
}