From d2192188a0b9d51e86afe8490c57d3f610e110be Mon Sep 17 00:00:00 2001 From: Alexandre VICTOOR Date: Sun, 27 Oct 2024 19:16:52 +0100 Subject: [PATCH 1/4] Fix List.removeAfter() bug --- __tests__/List.ts | 5 +++++ src/List.js | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/__tests__/List.ts b/__tests__/List.ts index 1fa808b807..709d7e2042 100644 --- a/__tests__/List.ts +++ b/__tests__/List.ts @@ -722,6 +722,11 @@ describe('List', () => { expect(o.get(0)).toBe('f'); }); + it('works with push and insert without phantom values', () => { + const v = List.of().set(287, 287).push(42).insert(33, 33); + expect(v.toJS().filter(item => item === 287)).toHaveLength(1); + }); + // TODO: assert that findIndex only calls the function as much as it needs to. it('forEach iterates in the correct order', () => { diff --git a/src/List.js b/src/List.js index be698316d3..e442b2b54e 100644 --- a/src/List.js +++ b/src/List.js @@ -304,7 +304,10 @@ class VNode { } removeAfter(ownerID, level, index) { - if (index === (level ? 1 << level : 0) || this.array.length === 0) { + if ( + index === (level ? 1 << (level + 1) : SIZE) - 1 || + this.array.length === 0 + ) { return this; } const sizeIndex = ((index - 1) >>> level) & MASK; From c89ec4c60aa6750dec48fafd8b9d9c43ae7f9eac Mon Sep 17 00:00:00 2001 From: Alexandre VICTOOR Date: Sat, 9 Nov 2024 21:44:28 +0100 Subject: [PATCH 2/4] fix: VNode.removeBefore & removeAfter bugs --- __tests__/List.ts | 10 +++++++++- src/List.js | 7 +++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/__tests__/List.ts b/__tests__/List.ts index 709d7e2042..2f03a8416c 100644 --- a/__tests__/List.ts +++ b/__tests__/List.ts @@ -722,9 +722,17 @@ describe('List', () => { expect(o.get(0)).toBe('f'); }); - it('works with push and insert without phantom values', () => { + it('works with push, set and insert without phantom values', () => { const v = List.of().set(287, 287).push(42).insert(33, 33); expect(v.toJS().filter(item => item === 287)).toHaveLength(1); + const v2 = List.of().push(0).unshift(-1).unshift(-2).pop().pop().set(2, 2); + expect(v2.toJS()).toEqual([-2, undefined, 2]); + const v3 = List.of().set(447, 447).push(0).insert(65, 65); + expect(v3.toJS().filter(item => item === 447)).toHaveLength(1); + const v4 = List.of().set(-28, -28).push(0).shift().set(-30, -30); + expect(v4.toJS().filter(item => item === -28)).toHaveLength(0); + const v5 = List.of().unshift(0).set(33, 33).shift().set(-35, -35); + expect(v5.toJS().filter(item => item === 0)).toHaveLength(0); }); // TODO: assert that findIndex only calls the function as much as it needs to. diff --git a/src/List.js b/src/List.js index e442b2b54e..26a946ece2 100644 --- a/src/List.js +++ b/src/List.js @@ -271,7 +271,10 @@ class VNode { // TODO: seems like these methods are very similar removeBefore(ownerID, level, index) { - if (index === level ? 1 << level : 0 || this.array.length === 0) { + if ( + (index & ((1 << (level + SHIFT)) - 1)) === 0 || + this.array.length === 0 + ) { return this; } const originIndex = (index >>> level) & MASK; @@ -305,7 +308,7 @@ class VNode { removeAfter(ownerID, level, index) { if ( - index === (level ? 1 << (level + 1) : SIZE) - 1 || + index === (level ? 1 << (level + SHIFT) : SIZE) || this.array.length === 0 ) { return this; From 60fce4fe9f140703773494d82a00ad1030b6ccf7 Mon Sep 17 00:00:00 2001 From: Julien Deniau Date: Tue, 19 Nov 2024 14:32:45 +0000 Subject: [PATCH 3/4] add test on the first 2000 integer Tested on 10 000, and the last failing number was 1023 --- __tests__/List.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/__tests__/List.ts b/__tests__/List.ts index 2f03a8416c..9b40b99d38 100644 --- a/__tests__/List.ts +++ b/__tests__/List.ts @@ -733,6 +733,20 @@ describe('List', () => { expect(v4.toJS().filter(item => item === -28)).toHaveLength(0); const v5 = List.of().unshift(0).set(33, 33).shift().set(-35, -35); expect(v5.toJS().filter(item => item === 0)).toHaveLength(0); + + // execute the same test as `v` but for the 2000 first integers + const isOkV1 = v => + List.of() + .set(v, v) + .push('pushed-value') + .insert(33, 'inserted-value') + .filter(item => item === v).size === 1; + + const arr = new Array(2000).fill(null).map((_, v) => v); + + const notOkArray = arr.filter(v => !isOkV1(v)); + + expect(notOkArray).toHaveLength(0); }); // TODO: assert that findIndex only calls the function as much as it needs to. From 0fc45d35d09ae57e9e1746c006d3186cf5d7e79d Mon Sep 17 00:00:00 2001 From: Julien Deniau Date: Tue, 19 Nov 2024 14:41:46 +0000 Subject: [PATCH 4/4] 5.0.3 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6592666323..13dc974bf7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "immutable", - "version": "5.0.2", + "version": "5.0.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "immutable", - "version": "5.0.2", + "version": "5.0.3", "license": "MIT", "devDependencies": { "@rollup/plugin-buble": "1.0.2", diff --git a/package.json b/package.json index d27ae6bd5b..cc287660c4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "immutable", - "version": "5.0.2", + "version": "5.0.3", "description": "Immutable Data Collections", "license": "MIT", "homepage": "https://immutable-js.com",