@isograph/react-disposable-state 0.0.0-main-ae4fea0e → 0.0.0-main-a8e129cf
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/.turbo/turbo-compile-libs.log +2 -2
- package/.turbo/turbo-tsc.log +1 -1
- package/dist/CacheItem.cjs +11 -8
- package/dist/CacheItem.d.cts.map +1 -1
- package/dist/CacheItem.d.mts.map +1 -1
- package/dist/CacheItem.mjs +11 -8
- package/dist/CacheItem.mjs.map +1 -1
- package/package.json +2 -2
- package/src/CacheItem.test.ts +40 -2
- package/src/CacheItem.ts +1 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
../.. | WARN Unsupported engine: wanted: {"node":"24.12.0"} (current: {"node":"v24.20.0","pnpm":"10.15.0"})
|
|
2
2
|
|
|
3
|
-
> @isograph/react-disposable-state@0.0.0-main-
|
|
3
|
+
> @isograph/react-disposable-state@0.0.0-main-a8e129cf compile-libs /home/runner/work/isograph/isograph/libs/isograph-react-disposable-state
|
|
4
4
|
> tsdown
|
|
5
5
|
|
|
6
6
|
[34mℹ[39m tsdown [2mv0.20.1[22m powered by rolldown [2mv1.0.0-rc.1[22m
|
|
7
7
|
[34mℹ[39m config file: [4m/home/runner/work/isograph/isograph/tsdown.config.ts[24m
|
|
8
|
-
(node:
|
|
8
|
+
(node:2729) [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///home/runner/work/isograph/isograph/tsdown.config.ts?no-cache=77ede110-960f-4f9b-b5d4-94a217d394dd is not specified and it doesn't parse as CommonJS.
|
|
9
9
|
Reparsing as ES module because module syntax was detected. This incurs a performance overhead.
|
|
10
10
|
To eliminate this warning, add "type": "module" to /home/runner/work/isograph/isograph/package.json.
|
|
11
11
|
(Use `node --trace-warnings ...` to show where the warning was created)
|
package/.turbo/turbo-tsc.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
../.. | WARN Unsupported engine: wanted: {"node":"24.12.0"} (current: {"node":"v24.20.0","pnpm":"10.15.0"})
|
|
2
2
|
|
|
3
|
-
> @isograph/react-disposable-state@0.0.0-main-
|
|
3
|
+
> @isograph/react-disposable-state@0.0.0-main-a8e129cf tsc /home/runner/work/isograph/isograph/libs/isograph-react-disposable-state
|
|
4
4
|
> tsc
|
|
5
5
|
|
package/dist/CacheItem.cjs
CHANGED
|
@@ -94,14 +94,17 @@ var CacheItem = class {
|
|
|
94
94
|
this.__state.temporaryRetainCount++;
|
|
95
95
|
const clearTemporaryRetainByCallack = () => {
|
|
96
96
|
if (status === "ClearedByCallback") throw new Error("A temporary retain should only be cleared once. This indicates a bug in react-disposable-state.");
|
|
97
|
-
else if (status === "Uncleared")
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
97
|
+
else if (status === "Uncleared") {
|
|
98
|
+
status = "ClearedByCallback";
|
|
99
|
+
switch (this.__state.kind) {
|
|
100
|
+
case "InParentCacheAndNotDisposed":
|
|
101
|
+
this.__state.temporaryRetainCount--;
|
|
102
|
+
this.__maybeExitInParentCacheAndNotDisposedState(this.__state);
|
|
103
|
+
clearTimeout(timeoutId);
|
|
104
|
+
return;
|
|
105
|
+
case "NotInParentCacheAndDisposed":
|
|
106
|
+
case "NotInParentCacheAndNotDisposed": throw new Error("A temporary retain was cleared, for which the CacheItem is in an invalid state. This indicates a bug in react-disposable-state.");
|
|
107
|
+
}
|
|
105
108
|
}
|
|
106
109
|
};
|
|
107
110
|
const clearTemporaryRetainByTimeout = () => {
|
package/dist/CacheItem.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CacheItem.d.cts","names":[],"sources":["../src/CacheItem.ts"],"mappings":";;;KAQY,2BAAA;EACV,IAAA;AAAA;AAAA,KAEU,8BAAA;EACV,IAAA;EACA,KAAA,EAAO,CAAA;EACP,YAAA;EAGA,oBAAA;AAAA;AAAA,KAEU,2BAAA;EACV,IAAA;EACA,KAAA,EAAO,CAAA;EACP,YAAA;EACA,qBAAA;EAGA,oBAAA;EAGA,oBAAA;AAAA;AAAA,KAGU,cAAA,MACR,2BAAA,CAA4B,CAAA,IAC5B,8BAAA,CAA+B,CAAA,IAC/B,2BAAA;AAAA,KAEQ,gBAAA;EACV,mBAAA;AAAA;;;;;;;;;;;;;AANF;;;;;;;;;;;;cAoCa,SAAA;EAAA,QACH,OAAA;EAAA,QACA,SAAA;cAQN,OAAA,EAAS,OAAA,CAAQ,CAAA,GACjB,qBAAA,EAAuB,SAAA,EACvB,OAAA,EAAS,gBAAA;EAgBX,QAAA,CAAA,GAAY,CAAA;EAiBZ,4BAAA,CACE,wBAAA,EAA0B,SAAA,GACzB,eAAA,CAAgB,CAAA;EA+EnB,eAAA,CAAA,GAAmB,SAAA;
|
|
1
|
+
{"version":3,"file":"CacheItem.d.cts","names":[],"sources":["../src/CacheItem.ts"],"mappings":";;;KAQY,2BAAA;EACV,IAAA;AAAA;AAAA,KAEU,8BAAA;EACV,IAAA;EACA,KAAA,EAAO,CAAA;EACP,YAAA;EAGA,oBAAA;AAAA;AAAA,KAEU,2BAAA;EACV,IAAA;EACA,KAAA,EAAO,CAAA;EACP,YAAA;EACA,qBAAA;EAGA,oBAAA;EAGA,oBAAA;AAAA;AAAA,KAGU,cAAA,MACR,2BAAA,CAA4B,CAAA,IAC5B,8BAAA,CAA+B,CAAA,IAC/B,2BAAA;AAAA,KAEQ,gBAAA;EACV,mBAAA;AAAA;;;;;;;;;;;;;AANF;;;;;;;;;;;;cAoCa,SAAA;EAAA,QACH,OAAA;EAAA,QACA,SAAA;cAQN,OAAA,EAAS,OAAA,CAAQ,CAAA,GACjB,qBAAA,EAAuB,SAAA,EACvB,OAAA,EAAS,gBAAA;EAgBX,QAAA,CAAA,GAAY,CAAA;EAiBZ,4BAAA,CACE,wBAAA,EAA0B,SAAA,GACzB,eAAA,CAAgB,CAAA;EA+EnB,eAAA,CAAA,GAAmB,SAAA;EAsEnB,eAAA,CAAA,GAAmB,SAAA;EAAA,QAqEX,2CAAA;EAAA,QAoBA,8CAAA;AAAA;AAAA,iBAYM,kCAAA,GAAA,CACd,OAAA,EAAS,OAAA,CAAQ,CAAA,GACjB,qBAAA,EAAuB,SAAA,EACvB,OAAA,EAAS,gBAAA,WACP,SAAA,CAAU,CAAA,GAAI,SAAA"}
|
package/dist/CacheItem.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CacheItem.d.mts","names":[],"sources":["../src/CacheItem.ts"],"mappings":";;;KAQY,2BAAA;EACV,IAAA;AAAA;AAAA,KAEU,8BAAA;EACV,IAAA;EACA,KAAA,EAAO,CAAA;EACP,YAAA;EAGA,oBAAA;AAAA;AAAA,KAEU,2BAAA;EACV,IAAA;EACA,KAAA,EAAO,CAAA;EACP,YAAA;EACA,qBAAA;EAGA,oBAAA;EAGA,oBAAA;AAAA;AAAA,KAGU,cAAA,MACR,2BAAA,CAA4B,CAAA,IAC5B,8BAAA,CAA+B,CAAA,IAC/B,2BAAA;AAAA,KAEQ,gBAAA;EACV,mBAAA;AAAA;;;;;;;;;;;;;AANF;;;;;;;;;;;;cAoCa,SAAA;EAAA,QACH,OAAA;EAAA,QACA,SAAA;cAQN,OAAA,EAAS,OAAA,CAAQ,CAAA,GACjB,qBAAA,EAAuB,SAAA,EACvB,OAAA,EAAS,gBAAA;EAgBX,QAAA,CAAA,GAAY,CAAA;EAiBZ,4BAAA,CACE,wBAAA,EAA0B,SAAA,GACzB,eAAA,CAAgB,CAAA;EA+EnB,eAAA,CAAA,GAAmB,SAAA;
|
|
1
|
+
{"version":3,"file":"CacheItem.d.mts","names":[],"sources":["../src/CacheItem.ts"],"mappings":";;;KAQY,2BAAA;EACV,IAAA;AAAA;AAAA,KAEU,8BAAA;EACV,IAAA;EACA,KAAA,EAAO,CAAA;EACP,YAAA;EAGA,oBAAA;AAAA;AAAA,KAEU,2BAAA;EACV,IAAA;EACA,KAAA,EAAO,CAAA;EACP,YAAA;EACA,qBAAA;EAGA,oBAAA;EAGA,oBAAA;AAAA;AAAA,KAGU,cAAA,MACR,2BAAA,CAA4B,CAAA,IAC5B,8BAAA,CAA+B,CAAA,IAC/B,2BAAA;AAAA,KAEQ,gBAAA;EACV,mBAAA;AAAA;;;;;;;;;;;;;AANF;;;;;;;;;;;;cAoCa,SAAA;EAAA,QACH,OAAA;EAAA,QACA,SAAA;cAQN,OAAA,EAAS,OAAA,CAAQ,CAAA,GACjB,qBAAA,EAAuB,SAAA,EACvB,OAAA,EAAS,gBAAA;EAgBX,QAAA,CAAA,GAAY,CAAA;EAiBZ,4BAAA,CACE,wBAAA,EAA0B,SAAA,GACzB,eAAA,CAAgB,CAAA;EA+EnB,eAAA,CAAA,GAAmB,SAAA;EAsEnB,eAAA,CAAA,GAAmB,SAAA;EAAA,QAqEX,2CAAA;EAAA,QAoBA,8CAAA;AAAA;AAAA,iBAYM,kCAAA,GAAA,CACd,OAAA,EAAS,OAAA,CAAQ,CAAA,GACjB,qBAAA,EAAuB,SAAA,EACvB,OAAA,EAAS,gBAAA,WACP,SAAA,CAAU,CAAA,GAAI,SAAA"}
|
package/dist/CacheItem.mjs
CHANGED
|
@@ -93,14 +93,17 @@ var CacheItem = class {
|
|
|
93
93
|
this.__state.temporaryRetainCount++;
|
|
94
94
|
const clearTemporaryRetainByCallack = () => {
|
|
95
95
|
if (status === "ClearedByCallback") throw new Error("A temporary retain should only be cleared once. This indicates a bug in react-disposable-state.");
|
|
96
|
-
else if (status === "Uncleared")
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
96
|
+
else if (status === "Uncleared") {
|
|
97
|
+
status = "ClearedByCallback";
|
|
98
|
+
switch (this.__state.kind) {
|
|
99
|
+
case "InParentCacheAndNotDisposed":
|
|
100
|
+
this.__state.temporaryRetainCount--;
|
|
101
|
+
this.__maybeExitInParentCacheAndNotDisposedState(this.__state);
|
|
102
|
+
clearTimeout(timeoutId);
|
|
103
|
+
return;
|
|
104
|
+
case "NotInParentCacheAndDisposed":
|
|
105
|
+
case "NotInParentCacheAndNotDisposed": throw new Error("A temporary retain was cleared, for which the CacheItem is in an invalid state. This indicates a bug in react-disposable-state.");
|
|
106
|
+
}
|
|
104
107
|
}
|
|
105
108
|
};
|
|
106
109
|
const clearTemporaryRetainByTimeout = () => {
|
package/dist/CacheItem.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CacheItem.mjs","names":[],"sources":["../src/CacheItem.ts"],"sourcesContent":["import type {\n CleanupFn,\n Factory,\n ItemCleanupPair,\n} from '@isograph/disposable-types';\n\nconst DEFAULT_TEMPORARY_RETAIN_TIME = 5000;\n\nexport type NotInParentCacheAndDisposed = {\n kind: 'NotInParentCacheAndDisposed';\n};\nexport type NotInParentCacheAndNotDisposed<T> = {\n kind: 'NotInParentCacheAndNotDisposed';\n value: T;\n disposeValue: () => void;\n\n // Invariant: >0\n permanentRetainCount: number;\n};\nexport type InParentCacheAndNotDisposed<T> = {\n kind: 'InParentCacheAndNotDisposed';\n value: T;\n disposeValue: () => void;\n removeFromParentCache: () => void;\n\n // Invariant: >0\n temporaryRetainCount: number;\n\n // Invariant: >= 0\n permanentRetainCount: number;\n};\n\nexport type CacheItemState<T> =\n | InParentCacheAndNotDisposed<T>\n | NotInParentCacheAndNotDisposed<T>\n | NotInParentCacheAndDisposed;\n\nexport type CacheItemOptions = {\n temporaryRetainTime: number;\n};\n\n// TODO don't export this class, only export type (interface) instead\n// TODO convert cacheitem impl to a getter and setter and free functions\n\n/**\n * CacheItem:\n *\n * Terminology:\n * - TRC = Temporary Retain Count\n * - PRC = Permanent Retain Count\n *\n * A CacheItem<T> can be in three states:\n * In parent cache? | Item disposed? | TRC | PRC | Name\n * -----------------+----------------+-----+-----+-------------------------------\n * In parent cache | Not disposed | >0 | >=0 | InParentCacheAndNotDisposed\n * Removed | Not disposed | 0 | >0 | NotInParentCacheAndNotDisposed\n * Removed | Disposed | 0 | 0 | NotInParentCacheAndNotDisposed\n *\n * A cache item can only move down rows. As in, if its in the parent cache,\n * it can be removed. It can never be replaced in the parent cache. (If a\n * parent cache becomes full again, it will contain a new CacheItem.) The\n * contained item can be disposed, but never un-disposed.\n *\n * So, the valid transitions are:\n * - InParentCacheAndNotDisposed => NotInParentCacheAndNotDisposed\n * - InParentCacheAndNotDisposed => NotInParentCacheAndDisposed\n * - NotInParentCacheAndNotDisposed => NotInParentCacheAndDisposed\n */\nexport class CacheItem<T> {\n private __state: CacheItemState<T>;\n private __options: CacheItemOptions | null;\n\n // Private. Do not call this constructor directly. Use\n // createTemporarilyRetainedCacheItem instead. This is because this\n // constructor creates a CacheItem in an invalid state. It must be\n // temporarily retained to enter a valid state, and JavaScript doesn't\n // let you return a tuple from a constructor.\n constructor(\n factory: Factory<T>,\n removeFromParentCache: CleanupFn,\n options: CacheItemOptions | void,\n ) {\n this.__options = options ?? null;\n const [value, disposeValue] = factory();\n this.__state = {\n kind: 'InParentCacheAndNotDisposed',\n value,\n disposeValue,\n removeFromParentCache,\n // NOTE: we are creating the CacheItem in an invalid state. This is okay, because\n // we are immediately calling .temporaryRetain.\n temporaryRetainCount: 0,\n permanentRetainCount: 0,\n };\n }\n\n getValue(): T {\n switch (this.__state.kind) {\n case 'InParentCacheAndNotDisposed': {\n return this.__state.value;\n }\n case 'NotInParentCacheAndNotDisposed': {\n return this.__state.value;\n }\n case 'NotInParentCacheAndDisposed': {\n throw new Error(\n 'Attempted to access disposed value from CacheItem. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n }\n\n permanentRetainIfNotDisposed(\n disposeOfTemporaryRetain: CleanupFn,\n ): ItemCleanupPair<T> | null {\n switch (this.__state.kind) {\n case 'InParentCacheAndNotDisposed': {\n let cleared = false;\n this.__state.permanentRetainCount++;\n disposeOfTemporaryRetain();\n return [\n this.__state.value,\n () => {\n if (cleared) {\n throw new Error(\n 'A permanent retain should only be cleared once. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n cleared = true;\n switch (this.__state.kind) {\n case 'InParentCacheAndNotDisposed': {\n this.__state.permanentRetainCount--;\n this.__maybeExitInParentCacheAndNotDisposedState(this.__state);\n return;\n }\n case 'NotInParentCacheAndNotDisposed': {\n this.__state.permanentRetainCount--;\n this.__maybeExitNotInParentCacheAndNotDisposedState(\n this.__state,\n );\n return;\n }\n case 'NotInParentCacheAndDisposed': {\n throw new Error(\n 'CacheItem was in a disposed state, but there existed a permanent retain. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n },\n ];\n }\n case 'NotInParentCacheAndNotDisposed': {\n let cleared = false;\n this.__state.permanentRetainCount++;\n disposeOfTemporaryRetain();\n return [\n this.__state.value,\n () => {\n if (cleared) {\n throw new Error(\n 'A permanent retain should only be cleared once. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n cleared = true;\n switch (this.__state.kind) {\n case 'NotInParentCacheAndNotDisposed': {\n this.__state.permanentRetainCount--;\n this.__maybeExitNotInParentCacheAndNotDisposedState(\n this.__state,\n );\n return;\n }\n case 'InParentCacheAndNotDisposed':\n case 'NotInParentCacheAndDisposed': {\n throw new Error(\n 'CacheItem was in an unexpected state. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n },\n ];\n }\n case 'NotInParentCacheAndDisposed': {\n // The CacheItem is disposed, so disposeOfTemporaryRetain is a no-op\n return null;\n }\n }\n }\n\n temporaryRetain(): CleanupFn {\n type TemporaryRetainStatus =\n | 'Uncleared'\n | 'ClearedByCallback'\n | 'ClearedByTimeout';\n\n switch (this.__state.kind) {\n case 'InParentCacheAndNotDisposed': {\n let status: TemporaryRetainStatus = 'Uncleared';\n this.__state.temporaryRetainCount++;\n const clearTemporaryRetainByCallack: CleanupFn = () => {\n if (status === 'ClearedByCallback') {\n throw new Error(\n 'A temporary retain should only be cleared once. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n } else if (status === 'Uncleared') {\n switch (this.__state.kind) {\n case 'InParentCacheAndNotDisposed': {\n this.__state.temporaryRetainCount--;\n this.__maybeExitInParentCacheAndNotDisposedState(this.__state);\n clearTimeout(timeoutId);\n return;\n }\n case 'NotInParentCacheAndDisposed':\n case 'NotInParentCacheAndNotDisposed': {\n throw new Error(\n 'A temporary retain was cleared, for which the CacheItem is in an invalid state. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n }\n };\n\n const clearTemporaryRetainByTimeout = () => {\n status = 'ClearedByTimeout';\n switch (this.__state.kind) {\n case 'InParentCacheAndNotDisposed': {\n this.__state.temporaryRetainCount--;\n this.__maybeExitInParentCacheAndNotDisposedState(this.__state);\n return;\n }\n case 'NotInParentCacheAndDisposed':\n case 'NotInParentCacheAndNotDisposed': {\n throw new Error(\n 'A temporary retain was cleared, for which the CacheItem is in an invalid state. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n };\n\n const timeoutId = setTimeout(\n clearTemporaryRetainByTimeout,\n this.__options?.temporaryRetainTime ?? DEFAULT_TEMPORARY_RETAIN_TIME,\n );\n return clearTemporaryRetainByCallack;\n }\n case 'NotInParentCacheAndDisposed':\n case 'NotInParentCacheAndNotDisposed': {\n throw new Error(\n 'temporaryRetain was called, for which the CacheItem is in an invalid state. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n }\n\n permanentRetain(): CleanupFn {\n switch (this.__state.kind) {\n case 'InParentCacheAndNotDisposed': {\n let cleared = false;\n this.__state.permanentRetainCount++;\n return () => {\n if (cleared) {\n throw new Error(\n 'A permanent retain should only be cleared once. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n cleared = true;\n switch (this.__state.kind) {\n case 'InParentCacheAndNotDisposed': {\n this.__state.permanentRetainCount--;\n this.__maybeExitInParentCacheAndNotDisposedState(this.__state);\n return;\n }\n case 'NotInParentCacheAndNotDisposed': {\n this.__state.permanentRetainCount--;\n this.__maybeExitNotInParentCacheAndNotDisposedState(this.__state);\n return;\n }\n case 'NotInParentCacheAndDisposed': {\n throw new Error(\n 'CacheItem was in a disposed state, but there existed a permanent retain. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n };\n }\n case 'NotInParentCacheAndNotDisposed': {\n let cleared = false;\n this.__state.permanentRetainCount++;\n return () => {\n if (cleared) {\n throw new Error(\n 'A permanent retain should only be cleared once. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n cleared = true;\n switch (this.__state.kind) {\n case 'NotInParentCacheAndNotDisposed': {\n this.__state.permanentRetainCount--;\n this.__maybeExitNotInParentCacheAndNotDisposedState(this.__state);\n return;\n }\n case 'InParentCacheAndNotDisposed':\n case 'NotInParentCacheAndDisposed': {\n throw new Error(\n 'CacheItem was in an unexpected state. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n };\n }\n case 'NotInParentCacheAndDisposed': {\n throw new Error(\n 'permanentRetain was called, but the CacheItem is in an invalid state. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n }\n\n private __maybeExitInParentCacheAndNotDisposedState(\n state: InParentCacheAndNotDisposed<T>,\n ) {\n if (state.temporaryRetainCount === 0 && state.permanentRetainCount === 0) {\n state.removeFromParentCache();\n state.disposeValue();\n this.__state = {\n kind: 'NotInParentCacheAndDisposed',\n };\n } else if (state.temporaryRetainCount === 0) {\n state.removeFromParentCache();\n this.__state = {\n kind: 'NotInParentCacheAndNotDisposed',\n value: state.value,\n disposeValue: state.disposeValue,\n permanentRetainCount: state.permanentRetainCount,\n };\n }\n }\n\n private __maybeExitNotInParentCacheAndNotDisposedState(\n state: NotInParentCacheAndNotDisposed<T>,\n ) {\n if (state.permanentRetainCount === 0) {\n state.disposeValue();\n this.__state = {\n kind: 'NotInParentCacheAndDisposed',\n };\n }\n }\n}\n\nexport function createTemporarilyRetainedCacheItem<T>(\n factory: Factory<T>,\n removeFromParentCache: CleanupFn,\n options: CacheItemOptions | void,\n): [CacheItem<T>, CleanupFn] {\n const cacheItem = new CacheItem(factory, removeFromParentCache, options);\n const disposeTemporaryRetain = cacheItem.temporaryRetain();\n return [cacheItem, disposeTemporaryRetain];\n}\n"],"mappings":";AAMA,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;AA8DtC,IAAa,YAAb,MAA0B;CASxB,YACE,SACA,uBACA,SACA;AACA,OAAK,YAAY,WAAW;EAC5B,MAAM,CAAC,OAAO,gBAAgB,SAAS;AACvC,OAAK,UAAU;GACb,MAAM;GACN;GACA;GACA;GAGA,sBAAsB;GACtB,sBAAsB;GACvB;;CAGH,WAAc;AACZ,UAAQ,KAAK,QAAQ,MAArB;GACE,KAAK,8BACH,QAAO,KAAK,QAAQ;GAEtB,KAAK,iCACH,QAAO,KAAK,QAAQ;GAEtB,KAAK,8BACH,OAAM,IAAI,MACR,qGAED;;;CAKP,6BACE,0BAC2B;AAC3B,UAAQ,KAAK,QAAQ,MAArB;GACE,KAAK,+BAA+B;IAClC,IAAI,UAAU;AACd,SAAK,QAAQ;AACb,8BAA0B;AAC1B,WAAO,CACL,KAAK,QAAQ,aACP;AACJ,SAAI,QACF,OAAM,IAAI,MACR,kGAED;AAEH,eAAU;AACV,aAAQ,KAAK,QAAQ,MAArB;MACE,KAAK;AACH,YAAK,QAAQ;AACb,YAAK,4CAA4C,KAAK,QAAQ;AAC9D;MAEF,KAAK;AACH,YAAK,QAAQ;AACb,YAAK,+CACH,KAAK,QACN;AACD;MAEF,KAAK,8BACH,OAAM,IAAI,MACR,2HAED;;MAIR;;GAEH,KAAK,kCAAkC;IACrC,IAAI,UAAU;AACd,SAAK,QAAQ;AACb,8BAA0B;AAC1B,WAAO,CACL,KAAK,QAAQ,aACP;AACJ,SAAI,QACF,OAAM,IAAI,MACR,kGAED;AAEH,eAAU;AACV,aAAQ,KAAK,QAAQ,MAArB;MACE,KAAK;AACH,YAAK,QAAQ;AACb,YAAK,+CACH,KAAK,QACN;AACD;MAEF,KAAK;MACL,KAAK,8BACH,OAAM,IAAI,MACR,wFAED;;MAIR;;GAEH,KAAK,8BAEH,QAAO;;;CAKb,kBAA6B;AAM3B,UAAQ,KAAK,QAAQ,MAArB;GACE,KAAK,+BAA+B;IAClC,IAAI,SAAgC;AACpC,SAAK,QAAQ;IACb,MAAM,sCAAiD;AACrD,SAAI,WAAW,oBACb,OAAM,IAAI,MACR,kGAED;cACQ,WAAW,YACpB,SAAQ,KAAK,QAAQ,MAArB;MACE,KAAK;AACH,YAAK,QAAQ;AACb,YAAK,4CAA4C,KAAK,QAAQ;AAC9D,oBAAa,UAAU;AACvB;MAEF,KAAK;MACL,KAAK,iCACH,OAAM,IAAI,MACR,kIAED;;;IAMT,MAAM,sCAAsC;AAC1C,cAAS;AACT,aAAQ,KAAK,QAAQ,MAArB;MACE,KAAK;AACH,YAAK,QAAQ;AACb,YAAK,4CAA4C,KAAK,QAAQ;AAC9D;MAEF,KAAK;MACL,KAAK,iCACH,OAAM,IAAI,MACR,kIAED;;;IAKP,MAAM,YAAY,WAChB,+BACA,KAAK,WAAW,uBAAuB,8BACxC;AACD,WAAO;;GAET,KAAK;GACL,KAAK,iCACH,OAAM,IAAI,MACR,8HAED;;;CAKP,kBAA6B;AAC3B,UAAQ,KAAK,QAAQ,MAArB;GACE,KAAK,+BAA+B;IAClC,IAAI,UAAU;AACd,SAAK,QAAQ;AACb,iBAAa;AACX,SAAI,QACF,OAAM,IAAI,MACR,kGAED;AAEH,eAAU;AACV,aAAQ,KAAK,QAAQ,MAArB;MACE,KAAK;AACH,YAAK,QAAQ;AACb,YAAK,4CAA4C,KAAK,QAAQ;AAC9D;MAEF,KAAK;AACH,YAAK,QAAQ;AACb,YAAK,+CAA+C,KAAK,QAAQ;AACjE;MAEF,KAAK,8BACH,OAAM,IAAI,MACR,2HAED;;;;GAKT,KAAK,kCAAkC;IACrC,IAAI,UAAU;AACd,SAAK,QAAQ;AACb,iBAAa;AACX,SAAI,QACF,OAAM,IAAI,MACR,kGAED;AAEH,eAAU;AACV,aAAQ,KAAK,QAAQ,MAArB;MACE,KAAK;AACH,YAAK,QAAQ;AACb,YAAK,+CAA+C,KAAK,QAAQ;AACjE;MAEF,KAAK;MACL,KAAK,8BACH,OAAM,IAAI,MACR,wFAED;;;;GAKT,KAAK,8BACH,OAAM,IAAI,MACR,wHAED;;;CAKP,AAAQ,4CACN,OACA;AACA,MAAI,MAAM,yBAAyB,KAAK,MAAM,yBAAyB,GAAG;AACxE,SAAM,uBAAuB;AAC7B,SAAM,cAAc;AACpB,QAAK,UAAU,EACb,MAAM,+BACP;aACQ,MAAM,yBAAyB,GAAG;AAC3C,SAAM,uBAAuB;AAC7B,QAAK,UAAU;IACb,MAAM;IACN,OAAO,MAAM;IACb,cAAc,MAAM;IACpB,sBAAsB,MAAM;IAC7B;;;CAIL,AAAQ,+CACN,OACA;AACA,MAAI,MAAM,yBAAyB,GAAG;AACpC,SAAM,cAAc;AACpB,QAAK,UAAU,EACb,MAAM,+BACP;;;;AAKP,SAAgB,mCACd,SACA,uBACA,SAC2B;CAC3B,MAAM,YAAY,IAAI,UAAU,SAAS,uBAAuB,QAAQ;AAExE,QAAO,CAAC,WADuB,UAAU,iBAAiB,CAChB"}
|
|
1
|
+
{"version":3,"file":"CacheItem.mjs","names":[],"sources":["../src/CacheItem.ts"],"sourcesContent":["import type {\n CleanupFn,\n Factory,\n ItemCleanupPair,\n} from '@isograph/disposable-types';\n\nconst DEFAULT_TEMPORARY_RETAIN_TIME = 5000;\n\nexport type NotInParentCacheAndDisposed = {\n kind: 'NotInParentCacheAndDisposed';\n};\nexport type NotInParentCacheAndNotDisposed<T> = {\n kind: 'NotInParentCacheAndNotDisposed';\n value: T;\n disposeValue: () => void;\n\n // Invariant: >0\n permanentRetainCount: number;\n};\nexport type InParentCacheAndNotDisposed<T> = {\n kind: 'InParentCacheAndNotDisposed';\n value: T;\n disposeValue: () => void;\n removeFromParentCache: () => void;\n\n // Invariant: >0\n temporaryRetainCount: number;\n\n // Invariant: >= 0\n permanentRetainCount: number;\n};\n\nexport type CacheItemState<T> =\n | InParentCacheAndNotDisposed<T>\n | NotInParentCacheAndNotDisposed<T>\n | NotInParentCacheAndDisposed;\n\nexport type CacheItemOptions = {\n temporaryRetainTime: number;\n};\n\n// TODO don't export this class, only export type (interface) instead\n// TODO convert cacheitem impl to a getter and setter and free functions\n\n/**\n * CacheItem:\n *\n * Terminology:\n * - TRC = Temporary Retain Count\n * - PRC = Permanent Retain Count\n *\n * A CacheItem<T> can be in three states:\n * In parent cache? | Item disposed? | TRC | PRC | Name\n * -----------------+----------------+-----+-----+-------------------------------\n * In parent cache | Not disposed | >0 | >=0 | InParentCacheAndNotDisposed\n * Removed | Not disposed | 0 | >0 | NotInParentCacheAndNotDisposed\n * Removed | Disposed | 0 | 0 | NotInParentCacheAndNotDisposed\n *\n * A cache item can only move down rows. As in, if its in the parent cache,\n * it can be removed. It can never be replaced in the parent cache. (If a\n * parent cache becomes full again, it will contain a new CacheItem.) The\n * contained item can be disposed, but never un-disposed.\n *\n * So, the valid transitions are:\n * - InParentCacheAndNotDisposed => NotInParentCacheAndNotDisposed\n * - InParentCacheAndNotDisposed => NotInParentCacheAndDisposed\n * - NotInParentCacheAndNotDisposed => NotInParentCacheAndDisposed\n */\nexport class CacheItem<T> {\n private __state: CacheItemState<T>;\n private __options: CacheItemOptions | null;\n\n // Private. Do not call this constructor directly. Use\n // createTemporarilyRetainedCacheItem instead. This is because this\n // constructor creates a CacheItem in an invalid state. It must be\n // temporarily retained to enter a valid state, and JavaScript doesn't\n // let you return a tuple from a constructor.\n constructor(\n factory: Factory<T>,\n removeFromParentCache: CleanupFn,\n options: CacheItemOptions | void,\n ) {\n this.__options = options ?? null;\n const [value, disposeValue] = factory();\n this.__state = {\n kind: 'InParentCacheAndNotDisposed',\n value,\n disposeValue,\n removeFromParentCache,\n // NOTE: we are creating the CacheItem in an invalid state. This is okay, because\n // we are immediately calling .temporaryRetain.\n temporaryRetainCount: 0,\n permanentRetainCount: 0,\n };\n }\n\n getValue(): T {\n switch (this.__state.kind) {\n case 'InParentCacheAndNotDisposed': {\n return this.__state.value;\n }\n case 'NotInParentCacheAndNotDisposed': {\n return this.__state.value;\n }\n case 'NotInParentCacheAndDisposed': {\n throw new Error(\n 'Attempted to access disposed value from CacheItem. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n }\n\n permanentRetainIfNotDisposed(\n disposeOfTemporaryRetain: CleanupFn,\n ): ItemCleanupPair<T> | null {\n switch (this.__state.kind) {\n case 'InParentCacheAndNotDisposed': {\n let cleared = false;\n this.__state.permanentRetainCount++;\n disposeOfTemporaryRetain();\n return [\n this.__state.value,\n () => {\n if (cleared) {\n throw new Error(\n 'A permanent retain should only be cleared once. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n cleared = true;\n switch (this.__state.kind) {\n case 'InParentCacheAndNotDisposed': {\n this.__state.permanentRetainCount--;\n this.__maybeExitInParentCacheAndNotDisposedState(this.__state);\n return;\n }\n case 'NotInParentCacheAndNotDisposed': {\n this.__state.permanentRetainCount--;\n this.__maybeExitNotInParentCacheAndNotDisposedState(\n this.__state,\n );\n return;\n }\n case 'NotInParentCacheAndDisposed': {\n throw new Error(\n 'CacheItem was in a disposed state, but there existed a permanent retain. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n },\n ];\n }\n case 'NotInParentCacheAndNotDisposed': {\n let cleared = false;\n this.__state.permanentRetainCount++;\n disposeOfTemporaryRetain();\n return [\n this.__state.value,\n () => {\n if (cleared) {\n throw new Error(\n 'A permanent retain should only be cleared once. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n cleared = true;\n switch (this.__state.kind) {\n case 'NotInParentCacheAndNotDisposed': {\n this.__state.permanentRetainCount--;\n this.__maybeExitNotInParentCacheAndNotDisposedState(\n this.__state,\n );\n return;\n }\n case 'InParentCacheAndNotDisposed':\n case 'NotInParentCacheAndDisposed': {\n throw new Error(\n 'CacheItem was in an unexpected state. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n },\n ];\n }\n case 'NotInParentCacheAndDisposed': {\n // The CacheItem is disposed, so disposeOfTemporaryRetain is a no-op\n return null;\n }\n }\n }\n\n temporaryRetain(): CleanupFn {\n type TemporaryRetainStatus =\n | 'Uncleared'\n | 'ClearedByCallback'\n | 'ClearedByTimeout';\n\n switch (this.__state.kind) {\n case 'InParentCacheAndNotDisposed': {\n let status: TemporaryRetainStatus = 'Uncleared';\n this.__state.temporaryRetainCount++;\n const clearTemporaryRetainByCallack: CleanupFn = () => {\n if (status === 'ClearedByCallback') {\n throw new Error(\n 'A temporary retain should only be cleared once. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n } else if (status === 'Uncleared') {\n status = 'ClearedByCallback';\n switch (this.__state.kind) {\n case 'InParentCacheAndNotDisposed': {\n this.__state.temporaryRetainCount--;\n this.__maybeExitInParentCacheAndNotDisposedState(this.__state);\n clearTimeout(timeoutId);\n return;\n }\n case 'NotInParentCacheAndDisposed':\n case 'NotInParentCacheAndNotDisposed': {\n throw new Error(\n 'A temporary retain was cleared, for which the CacheItem is in an invalid state. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n }\n };\n\n const clearTemporaryRetainByTimeout = () => {\n status = 'ClearedByTimeout';\n switch (this.__state.kind) {\n case 'InParentCacheAndNotDisposed': {\n this.__state.temporaryRetainCount--;\n this.__maybeExitInParentCacheAndNotDisposedState(this.__state);\n return;\n }\n case 'NotInParentCacheAndDisposed':\n case 'NotInParentCacheAndNotDisposed': {\n throw new Error(\n 'A temporary retain was cleared, for which the CacheItem is in an invalid state. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n };\n\n const timeoutId = setTimeout(\n clearTemporaryRetainByTimeout,\n this.__options?.temporaryRetainTime ?? DEFAULT_TEMPORARY_RETAIN_TIME,\n );\n return clearTemporaryRetainByCallack;\n }\n case 'NotInParentCacheAndDisposed':\n case 'NotInParentCacheAndNotDisposed': {\n throw new Error(\n 'temporaryRetain was called, for which the CacheItem is in an invalid state. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n }\n\n permanentRetain(): CleanupFn {\n switch (this.__state.kind) {\n case 'InParentCacheAndNotDisposed': {\n let cleared = false;\n this.__state.permanentRetainCount++;\n return () => {\n if (cleared) {\n throw new Error(\n 'A permanent retain should only be cleared once. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n cleared = true;\n switch (this.__state.kind) {\n case 'InParentCacheAndNotDisposed': {\n this.__state.permanentRetainCount--;\n this.__maybeExitInParentCacheAndNotDisposedState(this.__state);\n return;\n }\n case 'NotInParentCacheAndNotDisposed': {\n this.__state.permanentRetainCount--;\n this.__maybeExitNotInParentCacheAndNotDisposedState(this.__state);\n return;\n }\n case 'NotInParentCacheAndDisposed': {\n throw new Error(\n 'CacheItem was in a disposed state, but there existed a permanent retain. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n };\n }\n case 'NotInParentCacheAndNotDisposed': {\n let cleared = false;\n this.__state.permanentRetainCount++;\n return () => {\n if (cleared) {\n throw new Error(\n 'A permanent retain should only be cleared once. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n cleared = true;\n switch (this.__state.kind) {\n case 'NotInParentCacheAndNotDisposed': {\n this.__state.permanentRetainCount--;\n this.__maybeExitNotInParentCacheAndNotDisposedState(this.__state);\n return;\n }\n case 'InParentCacheAndNotDisposed':\n case 'NotInParentCacheAndDisposed': {\n throw new Error(\n 'CacheItem was in an unexpected state. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n };\n }\n case 'NotInParentCacheAndDisposed': {\n throw new Error(\n 'permanentRetain was called, but the CacheItem is in an invalid state. ' +\n 'This indicates a bug in react-disposable-state.',\n );\n }\n }\n }\n\n private __maybeExitInParentCacheAndNotDisposedState(\n state: InParentCacheAndNotDisposed<T>,\n ) {\n if (state.temporaryRetainCount === 0 && state.permanentRetainCount === 0) {\n state.removeFromParentCache();\n state.disposeValue();\n this.__state = {\n kind: 'NotInParentCacheAndDisposed',\n };\n } else if (state.temporaryRetainCount === 0) {\n state.removeFromParentCache();\n this.__state = {\n kind: 'NotInParentCacheAndNotDisposed',\n value: state.value,\n disposeValue: state.disposeValue,\n permanentRetainCount: state.permanentRetainCount,\n };\n }\n }\n\n private __maybeExitNotInParentCacheAndNotDisposedState(\n state: NotInParentCacheAndNotDisposed<T>,\n ) {\n if (state.permanentRetainCount === 0) {\n state.disposeValue();\n this.__state = {\n kind: 'NotInParentCacheAndDisposed',\n };\n }\n }\n}\n\nexport function createTemporarilyRetainedCacheItem<T>(\n factory: Factory<T>,\n removeFromParentCache: CleanupFn,\n options: CacheItemOptions | void,\n): [CacheItem<T>, CleanupFn] {\n const cacheItem = new CacheItem(factory, removeFromParentCache, options);\n const disposeTemporaryRetain = cacheItem.temporaryRetain();\n return [cacheItem, disposeTemporaryRetain];\n}\n"],"mappings":"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"}
|
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-a8e129cf",
|
|
4
4
|
"description": "Primitives for managing disposable state in React",
|
|
5
5
|
"homepage": "https://isograph.dev",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"author": "Isograph Labs",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@isograph/disposable-types": "0.0.0-main-
|
|
11
|
+
"@isograph/disposable-types": "0.0.0-main-a8e129cf"
|
|
12
12
|
},
|
|
13
13
|
"peerDependencies": {
|
|
14
14
|
"react": "^18.0.0 || ^19.0.0"
|
package/src/CacheItem.test.ts
CHANGED
|
@@ -153,7 +153,45 @@ describe('CacheItem', () => {
|
|
|
153
153
|
|
|
154
154
|
expect(() => {
|
|
155
155
|
disposeTemporaryRetain();
|
|
156
|
-
}).toThrow();
|
|
156
|
+
}).toThrow('A temporary retain should only be cleared once.');
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe('Item that is temporarily retained twice', () => {
|
|
161
|
+
// A second clear of one temporary retain while the other still holds the
|
|
162
|
+
// item: without the status transition the count is decremented twice, the
|
|
163
|
+
// item leaves the parent cache, and the other holder's clear finds it in an
|
|
164
|
+
// invalid state.
|
|
165
|
+
test('Clearing the same temporary retain twice throws and leaves the other retain intact', () => {
|
|
166
|
+
const removeFromParentCache = vi.fn();
|
|
167
|
+
const disposeItem = vi.fn();
|
|
168
|
+
|
|
169
|
+
const factory = vi.fn(() => {
|
|
170
|
+
const ret: ItemCleanupPair<number> = [1, disposeItem];
|
|
171
|
+
return ret;
|
|
172
|
+
});
|
|
173
|
+
const [cacheItem, disposeTemporaryRetain1] =
|
|
174
|
+
createTemporarilyRetainedCacheItem<number>(
|
|
175
|
+
factory,
|
|
176
|
+
removeFromParentCache,
|
|
177
|
+
);
|
|
178
|
+
const disposeTemporaryRetain2 = cacheItem.temporaryRetain();
|
|
179
|
+
|
|
180
|
+
disposeTemporaryRetain1();
|
|
181
|
+
expect(() => {
|
|
182
|
+
disposeTemporaryRetain1();
|
|
183
|
+
}).toThrow('A temporary retain should only be cleared once.');
|
|
184
|
+
|
|
185
|
+
const state = getState(cacheItem);
|
|
186
|
+
assert(state.kind === 'InParentCacheAndNotDisposed');
|
|
187
|
+
expect(state.temporaryRetainCount).toEqual(1);
|
|
188
|
+
expect(removeFromParentCache).not.toHaveBeenCalled();
|
|
189
|
+
expect(disposeItem).not.toHaveBeenCalled();
|
|
190
|
+
|
|
191
|
+
disposeTemporaryRetain2();
|
|
192
|
+
expect(getState(cacheItem).kind).toEqual('NotInParentCacheAndDisposed');
|
|
193
|
+
expect(removeFromParentCache).toHaveBeenCalledOnce();
|
|
194
|
+
expect(disposeItem).toHaveBeenCalledOnce();
|
|
157
195
|
});
|
|
158
196
|
});
|
|
159
197
|
|
|
@@ -213,7 +251,7 @@ describe('CacheItem', () => {
|
|
|
213
251
|
|
|
214
252
|
expect(() => {
|
|
215
253
|
disposeTemporaryRetain();
|
|
216
|
-
}).toThrow();
|
|
254
|
+
}).toThrow('A temporary retain should only be cleared once.');
|
|
217
255
|
});
|
|
218
256
|
|
|
219
257
|
test('Item is disposed when the permanently retain is disposed', () => {
|
package/src/CacheItem.ts
CHANGED
|
@@ -209,6 +209,7 @@ export class CacheItem<T> {
|
|
|
209
209
|
'This indicates a bug in react-disposable-state.',
|
|
210
210
|
);
|
|
211
211
|
} else if (status === 'Uncleared') {
|
|
212
|
+
status = 'ClearedByCallback';
|
|
212
213
|
switch (this.__state.kind) {
|
|
213
214
|
case 'InParentCacheAndNotDisposed': {
|
|
214
215
|
this.__state.temporaryRetainCount--;
|