@isograph/react-disposable-state 0.0.0-main-9a9a4679 → 0.0.0-main-c8dd6185
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CacheItem.d.ts +14 -10
- package/dist/CacheItem.js +14 -10
- package/package.json +2 -2
- package/src/CacheItem.ts +14 -10
- package/src/ParentCache.test.ts +26 -22
- package/src/useCachedPrecommitValue.test.tsx +13 -29
package/dist/CacheItem.d.ts
CHANGED
@@ -21,21 +21,25 @@ export type CacheItemOptions = {
|
|
21
21
|
temporaryRetainTime: number;
|
22
22
|
};
|
23
23
|
/**
|
24
|
+
* CacheItem:
|
25
|
+
*
|
26
|
+
* Terminology:
|
24
27
|
* - TRC = Temporary Retain Count
|
25
28
|
* - PRC = Permanent Retain Count
|
26
29
|
*
|
27
|
-
* Rules:
|
28
|
-
* - In parent cache <=> TRC > 0
|
29
|
-
* - Removed from parent cache <=> TRC === 0
|
30
|
-
* - In parent cache => not disposed
|
31
|
-
* - Disposed => removed from parent cache + PRC === 0
|
32
|
-
*
|
33
30
|
* A CacheItem<T> can be in three states:
|
34
|
-
*
|
35
|
-
*
|
36
|
-
*
|
31
|
+
* In parent cache? | Item disposed? | TRC | PRC | Name
|
32
|
+
* -----------------+----------------+-----+-----+-------------------------------
|
33
|
+
* In parent cache | Not disposed | >0 | >=0 | InParentCacheAndNotDisposed
|
34
|
+
* Removed | Not disposed | 0 | >0 | NotInParentCacheAndNotDisposed
|
35
|
+
* Removed | Disposed | 0 | 0 | NotInParentCacheAndNotDisposed
|
36
|
+
*
|
37
|
+
* A cache item can only move down rows. As in, if its in the parent cache,
|
38
|
+
* it can be removed. It can never be replaced in the parent cache. (If a
|
39
|
+
* parent cache becomes full again, it will contain a new CacheItem.) The
|
40
|
+
* contained item can be disposed, but never un-disposed.
|
37
41
|
*
|
38
|
-
*
|
42
|
+
* So, the valid transitions are:
|
39
43
|
* - InParentCacheAndNotDisposed => NotInParentCacheAndNotDisposed
|
40
44
|
* - InParentCacheAndNotDisposed => NotInParentCacheAndDisposed
|
41
45
|
* - NotInParentCacheAndNotDisposed => NotInParentCacheAndDisposed
|
package/dist/CacheItem.js
CHANGED
@@ -5,21 +5,25 @@ const DEFAULT_TEMPORARY_RETAIN_TIME = 5000;
|
|
5
5
|
// TODO don't export this class, only export type (interface) instead
|
6
6
|
// TODO convert cacheitem impl to a getter and setter and free functions
|
7
7
|
/**
|
8
|
+
* CacheItem:
|
9
|
+
*
|
10
|
+
* Terminology:
|
8
11
|
* - TRC = Temporary Retain Count
|
9
12
|
* - PRC = Permanent Retain Count
|
10
13
|
*
|
11
|
-
* Rules:
|
12
|
-
* - In parent cache <=> TRC > 0
|
13
|
-
* - Removed from parent cache <=> TRC === 0
|
14
|
-
* - In parent cache => not disposed
|
15
|
-
* - Disposed => removed from parent cache + PRC === 0
|
16
|
-
*
|
17
14
|
* A CacheItem<T> can be in three states:
|
18
|
-
*
|
19
|
-
*
|
20
|
-
*
|
15
|
+
* In parent cache? | Item disposed? | TRC | PRC | Name
|
16
|
+
* -----------------+----------------+-----+-----+-------------------------------
|
17
|
+
* In parent cache | Not disposed | >0 | >=0 | InParentCacheAndNotDisposed
|
18
|
+
* Removed | Not disposed | 0 | >0 | NotInParentCacheAndNotDisposed
|
19
|
+
* Removed | Disposed | 0 | 0 | NotInParentCacheAndNotDisposed
|
20
|
+
*
|
21
|
+
* A cache item can only move down rows. As in, if its in the parent cache,
|
22
|
+
* it can be removed. It can never be replaced in the parent cache. (If a
|
23
|
+
* parent cache becomes full again, it will contain a new CacheItem.) The
|
24
|
+
* contained item can be disposed, but never un-disposed.
|
21
25
|
*
|
22
|
-
*
|
26
|
+
* So, the valid transitions are:
|
23
27
|
* - InParentCacheAndNotDisposed => NotInParentCacheAndNotDisposed
|
24
28
|
* - InParentCacheAndNotDisposed => NotInParentCacheAndDisposed
|
25
29
|
* - NotInParentCacheAndNotDisposed => NotInParentCacheAndDisposed
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@isograph/react-disposable-state",
|
3
|
-
"version": "0.0.0-main-
|
3
|
+
"version": "0.0.0-main-c8dd6185",
|
4
4
|
"description": "Primitives for managing disposable state in React",
|
5
5
|
"main": "dist/index.js",
|
6
6
|
"types": "dist/index.d.ts",
|
@@ -16,7 +16,7 @@
|
|
16
16
|
"prepack": "yarn run compile"
|
17
17
|
},
|
18
18
|
"dependencies": {
|
19
|
-
"@isograph/disposable-types": "0.0.0-main-
|
19
|
+
"@isograph/disposable-types": "0.0.0-main-c8dd6185",
|
20
20
|
"react": "^18.2.0"
|
21
21
|
},
|
22
22
|
"devDependencies": {
|
package/src/CacheItem.ts
CHANGED
@@ -43,21 +43,25 @@ export type CacheItemOptions = {
|
|
43
43
|
// TODO convert cacheitem impl to a getter and setter and free functions
|
44
44
|
|
45
45
|
/**
|
46
|
+
* CacheItem:
|
47
|
+
*
|
48
|
+
* Terminology:
|
46
49
|
* - TRC = Temporary Retain Count
|
47
50
|
* - PRC = Permanent Retain Count
|
48
51
|
*
|
49
|
-
* Rules:
|
50
|
-
* - In parent cache <=> TRC > 0
|
51
|
-
* - Removed from parent cache <=> TRC === 0
|
52
|
-
* - In parent cache => not disposed
|
53
|
-
* - Disposed => removed from parent cache + PRC === 0
|
54
|
-
*
|
55
52
|
* A CacheItem<T> can be in three states:
|
56
|
-
*
|
57
|
-
*
|
58
|
-
*
|
53
|
+
* In parent cache? | Item disposed? | TRC | PRC | Name
|
54
|
+
* -----------------+----------------+-----+-----+-------------------------------
|
55
|
+
* In parent cache | Not disposed | >0 | >=0 | InParentCacheAndNotDisposed
|
56
|
+
* Removed | Not disposed | 0 | >0 | NotInParentCacheAndNotDisposed
|
57
|
+
* Removed | Disposed | 0 | 0 | NotInParentCacheAndNotDisposed
|
58
|
+
*
|
59
|
+
* A cache item can only move down rows. As in, if its in the parent cache,
|
60
|
+
* it can be removed. It can never be replaced in the parent cache. (If a
|
61
|
+
* parent cache becomes full again, it will contain a new CacheItem.) The
|
62
|
+
* contained item can be disposed, but never un-disposed.
|
59
63
|
*
|
60
|
-
*
|
64
|
+
* So, the valid transitions are:
|
61
65
|
* - InParentCacheAndNotDisposed => NotInParentCacheAndNotDisposed
|
62
66
|
* - InParentCacheAndNotDisposed => NotInParentCacheAndDisposed
|
63
67
|
* - NotInParentCacheAndNotDisposed => NotInParentCacheAndDisposed
|
package/src/ParentCache.test.ts
CHANGED
@@ -4,36 +4,40 @@ import { ItemCleanupPair } from '@isograph/disposable-types';
|
|
4
4
|
import { CacheItem } from './CacheItem';
|
5
5
|
|
6
6
|
function getValue<T>(cache: ParentCache<T>): CacheItem<T> | null {
|
7
|
-
return (cache as any).
|
7
|
+
return (cache as any).__cacheItem as CacheItem<T> | null;
|
8
8
|
}
|
9
9
|
|
10
10
|
describe('ParentCache', () => {
|
11
|
-
test(
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
test(
|
12
|
+
'Populated, emptied, repopulated cache is not ' +
|
13
|
+
're-emptied by original temporary retain being disposed',
|
14
|
+
() => {
|
15
|
+
const factory = vi.fn(() => {
|
16
|
+
const pair: ItemCleanupPair<number> = [1, vi.fn()];
|
17
|
+
return pair;
|
18
|
+
});
|
19
|
+
const parentCache = new ParentCache<number>(factory);
|
20
|
+
|
21
|
+
const [_cacheItem, value, clearTemporaryRetain] =
|
22
|
+
parentCache.getOrPopulateAndTemporaryRetain();
|
23
|
+
|
24
|
+
expect(factory.mock.calls.length).toBe(1);
|
25
|
+
assert(value === 1);
|
26
|
+
assert(getValue(parentCache) != null, 'Parent cache should not be empty');
|
27
|
+
|
28
|
+
parentCache.empty();
|
29
|
+
assert(getValue(parentCache) === null);
|
17
30
|
|
18
|
-
const [_cacheItem, value, clearTemporaryRetain] =
|
19
31
|
parentCache.getOrPopulateAndTemporaryRetain();
|
32
|
+
expect(factory.mock.calls.length).toBe(2);
|
20
33
|
|
21
|
-
|
22
|
-
assert(value === 1);
|
23
|
-
assert(getValue(parentCache) != null);
|
24
|
-
|
25
|
-
parentCache.empty();
|
26
|
-
assert(getValue(parentCache) === null);
|
27
|
-
|
28
|
-
parentCache.getOrPopulateAndTemporaryRetain();
|
29
|
-
expect(factory.mock.calls.length).toBe(2);
|
34
|
+
assert(getValue(parentCache) != null);
|
30
35
|
|
31
|
-
|
36
|
+
clearTemporaryRetain();
|
32
37
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
});
|
38
|
+
assert(getValue(parentCache) != null);
|
39
|
+
},
|
40
|
+
);
|
37
41
|
|
38
42
|
test('Clearing the only temporary retain removes the item from the parent cache', () => {
|
39
43
|
const factory = vi.fn(() => {
|
@@ -7,7 +7,7 @@ import { create } from 'react-test-renderer';
|
|
7
7
|
import { CacheItem, CacheItemState } from './CacheItem';
|
8
8
|
|
9
9
|
function getItem<T>(cache: ParentCache<T>): CacheItem<T> | null {
|
10
|
-
return (cache as any).
|
10
|
+
return (cache as any).__cacheItem;
|
11
11
|
}
|
12
12
|
|
13
13
|
function getState<T>(cacheItem: CacheItem<T>): CacheItemState<T> {
|
@@ -512,9 +512,8 @@ describe('useCachedPrecommitValue', () => {
|
|
512
512
|
);
|
513
513
|
|
514
514
|
test(
|
515
|
-
'
|
516
|
-
'
|
517
|
-
'temporarily retained',
|
515
|
+
'After render but before commit, the item will ' +
|
516
|
+
'be in the parent cache, temporarily retained',
|
518
517
|
async () => {
|
519
518
|
const disposeItem = vi.fn();
|
520
519
|
const factory = vi.fn(() => {
|
@@ -541,35 +540,20 @@ describe('useCachedPrecommitValue', () => {
|
|
541
540
|
// wat is going on?
|
542
541
|
//
|
543
542
|
// We want to test a scenario where the component unmounts before committing.
|
543
|
+
// However, we cannot distinguish between an unmount before commit and a
|
544
|
+
// render and a commit that hasn't happened yet.
|
544
545
|
//
|
545
|
-
//
|
546
|
-
//
|
547
|
-
//
|
548
|
-
|
549
|
-
setShowChildren(false);
|
550
|
-
return null;
|
551
|
-
}
|
552
|
-
|
553
|
-
let setShowChildren;
|
554
|
-
function ParentComponent({ children }) {
|
555
|
-
const [showChildren, _setShowChildren] = React.useState(true);
|
556
|
-
setShowChildren = _setShowChildren;
|
557
|
-
|
558
|
-
if (showChildren) {
|
559
|
-
return children;
|
560
|
-
} else {
|
561
|
-
return null;
|
562
|
-
}
|
563
|
-
}
|
546
|
+
// This can be simulated with suspense.
|
547
|
+
//
|
548
|
+
// This test and 'on initial render, it should call getOrPopulateAndTemporaryRetain'
|
549
|
+
// can be merged
|
564
550
|
|
551
|
+
const { promise, isResolvedRef } = promiseAndResolver();
|
565
552
|
const element = await awaitableCreate(
|
566
|
-
<
|
553
|
+
<React.Suspense fallback={null}>
|
567
554
|
<TestComponent />
|
568
|
-
<
|
569
|
-
</
|
570
|
-
// If we're not in concurrent mode, TestComponent will mount before
|
571
|
-
// unmounting. This perhaps is a bug in react-test-renderer. Regardless,
|
572
|
-
// we're not interested in that scenario.
|
555
|
+
<Suspender promise={promise} isResolvedRef={isResolvedRef} />
|
556
|
+
</React.Suspense>,
|
573
557
|
true,
|
574
558
|
);
|
575
559
|
|