Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions src/types/custom/ArraySchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,11 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V>, IR
// decoding only
protected $setAt(index: number, value: V, operation: OPERATION) {
if (
index === 0 &&
operation === OPERATION.ADD &&
this.items[index] !== undefined
) {
// handle decoding unshift
this.items.unshift(value);
// handle decoding unshift / insert at position
this.items.splice(index, 0, value);

} else if (operation === OPERATION.DELETE_AND_MOVE) {
this.items.splice(index, 1);
Expand Down Expand Up @@ -520,6 +519,18 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V>, IR

this.tmpItems.unshift(...items);

// Sort operations by ascending index to ensure correct encoding order.
// When consecutive unshifts occur, the decoder uses splice to insert at
// each index — this only works if lower indices are processed first.
// (See test "consecutive unshift calls should not break 'encodeAll'")
const changeSet = changeTree.isFiltered ? changeTree.filteredChanges : changeTree.changes;
changeSet.operations.sort((a, b) => a - b);
const newIndexes: { [index: number]: number } = {};
for (let i = 0; i < changeSet.operations.length; i++) {
newIndexes[changeSet.operations[i]] = i;
}
changeSet.indexes = newIndexes;

return this.items.unshift(...items);
}

Expand Down
2 changes: 1 addition & 1 deletion test/ArraySchema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@ describe("ArraySchema Tests", () => {
assertDeepStrictEqualEncodeAll(state);
});

xit("consecutive unshift calls should not break 'encodeAll'", () => {
it("consecutive unshift calls should not break 'encodeAll'", () => {
class State extends Schema {
@type(["number"]) arrayOfNumbers = new ArraySchema<number>();
}
Expand Down