initial update

This commit is contained in:
jackbeeby
2025-05-15 13:32:55 +10:00
commit 7b07a49fbe
4412 changed files with 909535 additions and 0 deletions

21
node_modules/@wry/caches/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019-2021 Ben Newman <ben@eloper.dev>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

9
node_modules/@wry/caches/README.md generated vendored Normal file
View File

@@ -0,0 +1,9 @@
# @wry/caches
Various cache implementations, including but not limited to
* `StrongCache`: A standard `Map`-like cache with a least-recently-used (LRU)
eviction policy and a callback hook for removed entries.
* `WeakCache`: Another LRU cache that holds its keys only weakly, so entries can be removed
once no longer retained elsewhere in the application.

245
node_modules/@wry/caches/lib/bundle.cjs generated vendored Normal file
View File

@@ -0,0 +1,245 @@
'use strict';
function defaultDispose$1() { }
var StrongCache = /** @class */ (function () {
function StrongCache(max, dispose) {
if (max === void 0) { max = Infinity; }
if (dispose === void 0) { dispose = defaultDispose$1; }
this.max = max;
this.dispose = dispose;
this.map = new Map();
this.newest = null;
this.oldest = null;
}
StrongCache.prototype.has = function (key) {
return this.map.has(key);
};
StrongCache.prototype.get = function (key) {
var node = this.getNode(key);
return node && node.value;
};
Object.defineProperty(StrongCache.prototype, "size", {
get: function () {
return this.map.size;
},
enumerable: false,
configurable: true
});
StrongCache.prototype.getNode = function (key) {
var node = this.map.get(key);
if (node && node !== this.newest) {
var older = node.older, newer = node.newer;
if (newer) {
newer.older = older;
}
if (older) {
older.newer = newer;
}
node.older = this.newest;
node.older.newer = node;
node.newer = null;
this.newest = node;
if (node === this.oldest) {
this.oldest = newer;
}
}
return node;
};
StrongCache.prototype.set = function (key, value) {
var node = this.getNode(key);
if (node) {
return node.value = value;
}
node = {
key: key,
value: value,
newer: null,
older: this.newest
};
if (this.newest) {
this.newest.newer = node;
}
this.newest = node;
this.oldest = this.oldest || node;
this.map.set(key, node);
return node.value;
};
StrongCache.prototype.clean = function () {
while (this.oldest && this.map.size > this.max) {
this.delete(this.oldest.key);
}
};
StrongCache.prototype.delete = function (key) {
var node = this.map.get(key);
if (node) {
if (node === this.newest) {
this.newest = node.older;
}
if (node === this.oldest) {
this.oldest = node.newer;
}
if (node.newer) {
node.newer.older = node.older;
}
if (node.older) {
node.older.newer = node.newer;
}
this.map.delete(key);
this.dispose(node.value, key);
return true;
}
return false;
};
return StrongCache;
}());
function noop() { }
var defaultDispose = noop;
var _WeakRef = typeof WeakRef !== "undefined"
? WeakRef
: function (value) {
return { deref: function () { return value; } };
};
var _WeakMap = typeof WeakMap !== "undefined" ? WeakMap : Map;
var _FinalizationRegistry = typeof FinalizationRegistry !== "undefined"
? FinalizationRegistry
: function () {
return {
register: noop,
unregister: noop,
};
};
var finalizationBatchSize = 10024;
var WeakCache = /** @class */ (function () {
function WeakCache(max, dispose) {
if (max === void 0) { max = Infinity; }
if (dispose === void 0) { dispose = defaultDispose; }
var _this = this;
this.max = max;
this.dispose = dispose;
this.map = new _WeakMap();
this.newest = null;
this.oldest = null;
this.unfinalizedNodes = new Set();
this.finalizationScheduled = false;
this.size = 0;
this.finalize = function () {
var iterator = _this.unfinalizedNodes.values();
for (var i = 0; i < finalizationBatchSize; i++) {
var node = iterator.next().value;
if (!node)
break;
_this.unfinalizedNodes.delete(node);
var key = node.key;
delete node.key;
node.keyRef = new _WeakRef(key);
_this.registry.register(key, node, node);
}
if (_this.unfinalizedNodes.size > 0) {
queueMicrotask(_this.finalize);
}
else {
_this.finalizationScheduled = false;
}
};
this.registry = new _FinalizationRegistry(this.deleteNode.bind(this));
}
WeakCache.prototype.has = function (key) {
return this.map.has(key);
};
WeakCache.prototype.get = function (key) {
var node = this.getNode(key);
return node && node.value;
};
WeakCache.prototype.getNode = function (key) {
var node = this.map.get(key);
if (node && node !== this.newest) {
var older = node.older, newer = node.newer;
if (newer) {
newer.older = older;
}
if (older) {
older.newer = newer;
}
node.older = this.newest;
node.older.newer = node;
node.newer = null;
this.newest = node;
if (node === this.oldest) {
this.oldest = newer;
}
}
return node;
};
WeakCache.prototype.set = function (key, value) {
var node = this.getNode(key);
if (node) {
return (node.value = value);
}
node = {
key: key,
value: value,
newer: null,
older: this.newest,
};
if (this.newest) {
this.newest.newer = node;
}
this.newest = node;
this.oldest = this.oldest || node;
this.scheduleFinalization(node);
this.map.set(key, node);
this.size++;
return node.value;
};
WeakCache.prototype.clean = function () {
while (this.oldest && this.size > this.max) {
this.deleteNode(this.oldest);
}
};
WeakCache.prototype.deleteNode = function (node) {
if (node === this.newest) {
this.newest = node.older;
}
if (node === this.oldest) {
this.oldest = node.newer;
}
if (node.newer) {
node.newer.older = node.older;
}
if (node.older) {
node.older.newer = node.newer;
}
this.size--;
var key = node.key || (node.keyRef && node.keyRef.deref());
this.dispose(node.value, key);
if (!node.keyRef) {
this.unfinalizedNodes.delete(node);
}
else {
this.registry.unregister(node);
}
if (key)
this.map.delete(key);
};
WeakCache.prototype.delete = function (key) {
var node = this.map.get(key);
if (node) {
this.deleteNode(node);
return true;
}
return false;
};
WeakCache.prototype.scheduleFinalization = function (node) {
this.unfinalizedNodes.add(node);
if (!this.finalizationScheduled) {
this.finalizationScheduled = true;
queueMicrotask(this.finalize);
}
};
return WeakCache;
}());
exports.StrongCache = StrongCache;
exports.WeakCache = WeakCache;
//# sourceMappingURL=bundle.cjs.map

1
node_modules/@wry/caches/lib/bundle.cjs.map generated vendored Normal file

File diff suppressed because one or more lines are too long

245
node_modules/@wry/caches/lib/bundle.cjs.native.js generated vendored Normal file
View File

@@ -0,0 +1,245 @@
'use strict';
function defaultDispose$1() { }
var StrongCache = /** @class */ (function () {
function StrongCache(max, dispose) {
if (max === void 0) { max = Infinity; }
if (dispose === void 0) { dispose = defaultDispose$1; }
this.max = max;
this.dispose = dispose;
this.map = new Map();
this.newest = null;
this.oldest = null;
}
StrongCache.prototype.has = function (key) {
return this.map.has(key);
};
StrongCache.prototype.get = function (key) {
var node = this.getNode(key);
return node && node.value;
};
Object.defineProperty(StrongCache.prototype, "size", {
get: function () {
return this.map.size;
},
enumerable: false,
configurable: true
});
StrongCache.prototype.getNode = function (key) {
var node = this.map.get(key);
if (node && node !== this.newest) {
var older = node.older, newer = node.newer;
if (newer) {
newer.older = older;
}
if (older) {
older.newer = newer;
}
node.older = this.newest;
node.older.newer = node;
node.newer = null;
this.newest = node;
if (node === this.oldest) {
this.oldest = newer;
}
}
return node;
};
StrongCache.prototype.set = function (key, value) {
var node = this.getNode(key);
if (node) {
return node.value = value;
}
node = {
key: key,
value: value,
newer: null,
older: this.newest
};
if (this.newest) {
this.newest.newer = node;
}
this.newest = node;
this.oldest = this.oldest || node;
this.map.set(key, node);
return node.value;
};
StrongCache.prototype.clean = function () {
while (this.oldest && this.map.size > this.max) {
this.delete(this.oldest.key);
}
};
StrongCache.prototype.delete = function (key) {
var node = this.map.get(key);
if (node) {
if (node === this.newest) {
this.newest = node.older;
}
if (node === this.oldest) {
this.oldest = node.newer;
}
if (node.newer) {
node.newer.older = node.older;
}
if (node.older) {
node.older.newer = node.newer;
}
this.map.delete(key);
this.dispose(node.value, key);
return true;
}
return false;
};
return StrongCache;
}());
function noop() { }
var defaultDispose = noop;
var _WeakRef = typeof WeakRef !== "undefined"
? WeakRef
: function (value) {
return { deref: function () { return value; } };
};
var _WeakMap = typeof WeakMap !== "undefined" ? WeakMap : Map;
var _FinalizationRegistry = typeof FinalizationRegistry !== "undefined"
? FinalizationRegistry
: function () {
return {
register: noop,
unregister: noop,
};
};
var finalizationBatchSize = 10024;
var WeakCache = /** @class */ (function () {
function WeakCache(max, dispose) {
if (max === void 0) { max = Infinity; }
if (dispose === void 0) { dispose = defaultDispose; }
var _this = this;
this.max = max;
this.dispose = dispose;
this.map = new _WeakMap();
this.newest = null;
this.oldest = null;
this.unfinalizedNodes = new Set();
this.finalizationScheduled = false;
this.size = 0;
this.finalize = function () {
var iterator = _this.unfinalizedNodes.values();
for (var i = 0; i < finalizationBatchSize; i++) {
var node = iterator.next().value;
if (!node)
break;
_this.unfinalizedNodes.delete(node);
var key = node.key;
delete node.key;
node.keyRef = new _WeakRef(key);
_this.registry.register(key, node, node);
}
if (_this.unfinalizedNodes.size > 0) {
queueMicrotask(_this.finalize);
}
else {
_this.finalizationScheduled = false;
}
};
this.registry = new _FinalizationRegistry(this.deleteNode.bind(this));
}
WeakCache.prototype.has = function (key) {
return this.map.has(key);
};
WeakCache.prototype.get = function (key) {
var node = this.getNode(key);
return node && node.value;
};
WeakCache.prototype.getNode = function (key) {
var node = this.map.get(key);
if (node && node !== this.newest) {
var older = node.older, newer = node.newer;
if (newer) {
newer.older = older;
}
if (older) {
older.newer = newer;
}
node.older = this.newest;
node.older.newer = node;
node.newer = null;
this.newest = node;
if (node === this.oldest) {
this.oldest = newer;
}
}
return node;
};
WeakCache.prototype.set = function (key, value) {
var node = this.getNode(key);
if (node) {
return (node.value = value);
}
node = {
key: key,
value: value,
newer: null,
older: this.newest,
};
if (this.newest) {
this.newest.newer = node;
}
this.newest = node;
this.oldest = this.oldest || node;
this.scheduleFinalization(node);
this.map.set(key, node);
this.size++;
return node.value;
};
WeakCache.prototype.clean = function () {
while (this.oldest && this.size > this.max) {
this.deleteNode(this.oldest);
}
};
WeakCache.prototype.deleteNode = function (node) {
if (node === this.newest) {
this.newest = node.older;
}
if (node === this.oldest) {
this.oldest = node.newer;
}
if (node.newer) {
node.newer.older = node.older;
}
if (node.older) {
node.older.newer = node.newer;
}
this.size--;
var key = node.key || (node.keyRef && node.keyRef.deref());
this.dispose(node.value, key);
if (!node.keyRef) {
this.unfinalizedNodes.delete(node);
}
else {
this.registry.unregister(node);
}
if (key)
this.map.delete(key);
};
WeakCache.prototype.delete = function (key) {
var node = this.map.get(key);
if (node) {
this.deleteNode(node);
return true;
}
return false;
};
WeakCache.prototype.scheduleFinalization = function (node) {
this.unfinalizedNodes.add(node);
if (!this.finalizationScheduled) {
this.finalizationScheduled = true;
queueMicrotask(this.finalize);
}
};
return WeakCache;
}());
exports.StrongCache = StrongCache;
exports.WeakCache = WeakCache;
//# sourceMappingURL=bundle.cjs.map

8
node_modules/@wry/caches/lib/common.d.ts generated vendored Normal file
View File

@@ -0,0 +1,8 @@
export interface CommonCache<K, V> {
has(key: K): boolean;
get(key: K): V | undefined;
set(key: K, value: V): V;
delete(key: K): boolean;
clean(): void;
readonly size: number;
}

2
node_modules/@wry/caches/lib/common.js generated vendored Normal file
View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=common.js.map

1
node_modules/@wry/caches/lib/common.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"common.js","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":""}

3
node_modules/@wry/caches/lib/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,3 @@
export type { CommonCache } from "./common.js";
export { StrongCache } from "./strong.js";
export { WeakCache } from "./weak.js";

3
node_modules/@wry/caches/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,3 @@
export { StrongCache } from "./strong.js";
export { WeakCache } from "./weak.js";
//# sourceMappingURL=index.js.map

1
node_modules/@wry/caches/lib/index.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}

16
node_modules/@wry/caches/lib/strong.d.ts generated vendored Normal file
View File

@@ -0,0 +1,16 @@
import type { CommonCache } from "./common";
export declare class StrongCache<K = any, V = any> implements CommonCache<K, V> {
private max;
dispose: (value: V, key: K) => void;
private map;
private newest;
private oldest;
constructor(max?: number, dispose?: (value: V, key: K) => void);
has(key: K): boolean;
get(key: K): V | undefined;
get size(): number;
private getNode;
set(key: K, value: V): V;
clean(): void;
delete(key: K): boolean;
}

86
node_modules/@wry/caches/lib/strong.js generated vendored Normal file
View File

@@ -0,0 +1,86 @@
function defaultDispose() { }
export class StrongCache {
constructor(max = Infinity, dispose = defaultDispose) {
this.max = max;
this.dispose = dispose;
this.map = new Map();
this.newest = null;
this.oldest = null;
}
has(key) {
return this.map.has(key);
}
get(key) {
const node = this.getNode(key);
return node && node.value;
}
get size() {
return this.map.size;
}
getNode(key) {
const node = this.map.get(key);
if (node && node !== this.newest) {
const { older, newer } = node;
if (newer) {
newer.older = older;
}
if (older) {
older.newer = newer;
}
node.older = this.newest;
node.older.newer = node;
node.newer = null;
this.newest = node;
if (node === this.oldest) {
this.oldest = newer;
}
}
return node;
}
set(key, value) {
let node = this.getNode(key);
if (node) {
return node.value = value;
}
node = {
key,
value,
newer: null,
older: this.newest
};
if (this.newest) {
this.newest.newer = node;
}
this.newest = node;
this.oldest = this.oldest || node;
this.map.set(key, node);
return node.value;
}
clean() {
while (this.oldest && this.map.size > this.max) {
this.delete(this.oldest.key);
}
}
delete(key) {
const node = this.map.get(key);
if (node) {
if (node === this.newest) {
this.newest = node.older;
}
if (node === this.oldest) {
this.oldest = node.newer;
}
if (node.newer) {
node.newer.older = node.older;
}
if (node.older) {
node.older.newer = node.newer;
}
this.map.delete(key);
this.dispose(node.value, key);
return true;
}
return false;
}
}
//# sourceMappingURL=strong.js.map

1
node_modules/@wry/caches/lib/strong.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"strong.js","sourceRoot":"","sources":["../src/strong.ts"],"names":[],"mappings":"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"}

22
node_modules/@wry/caches/lib/weak.d.ts generated vendored Normal file
View File

@@ -0,0 +1,22 @@
import type { CommonCache } from "./common";
export declare class WeakCache<K extends object = any, V = any> implements CommonCache<K, V> {
private max;
dispose: (value: V, key?: K) => void;
private map;
private registry;
private newest;
private oldest;
private unfinalizedNodes;
private finalizationScheduled;
size: number;
constructor(max?: number, dispose?: (value: V, key?: K) => void);
has(key: K): boolean;
get(key: K): V | undefined;
private getNode;
set(key: K, value: V): V;
clean(): void;
private deleteNode;
delete(key: K): boolean;
private scheduleFinalization;
private finalize;
}

143
node_modules/@wry/caches/lib/weak.js generated vendored Normal file
View File

@@ -0,0 +1,143 @@
function noop() { }
const defaultDispose = noop;
const _WeakRef = typeof WeakRef !== "undefined"
? WeakRef
: function (value) {
return { deref: () => value };
};
const _WeakMap = typeof WeakMap !== "undefined" ? WeakMap : Map;
const _FinalizationRegistry = typeof FinalizationRegistry !== "undefined"
? FinalizationRegistry
: function () {
return {
register: noop,
unregister: noop,
};
};
const finalizationBatchSize = 10024;
export class WeakCache {
constructor(max = Infinity, dispose = defaultDispose) {
this.max = max;
this.dispose = dispose;
this.map = new _WeakMap();
this.newest = null;
this.oldest = null;
this.unfinalizedNodes = new Set();
this.finalizationScheduled = false;
this.size = 0;
this.finalize = () => {
const iterator = this.unfinalizedNodes.values();
for (let i = 0; i < finalizationBatchSize; i++) {
const node = iterator.next().value;
if (!node)
break;
this.unfinalizedNodes.delete(node);
const key = node.key;
delete node.key;
node.keyRef = new _WeakRef(key);
this.registry.register(key, node, node);
}
if (this.unfinalizedNodes.size > 0) {
queueMicrotask(this.finalize);
}
else {
this.finalizationScheduled = false;
}
};
this.registry = new _FinalizationRegistry(this.deleteNode.bind(this));
}
has(key) {
return this.map.has(key);
}
get(key) {
const node = this.getNode(key);
return node && node.value;
}
getNode(key) {
const node = this.map.get(key);
if (node && node !== this.newest) {
const { older, newer } = node;
if (newer) {
newer.older = older;
}
if (older) {
older.newer = newer;
}
node.older = this.newest;
node.older.newer = node;
node.newer = null;
this.newest = node;
if (node === this.oldest) {
this.oldest = newer;
}
}
return node;
}
set(key, value) {
let node = this.getNode(key);
if (node) {
return (node.value = value);
}
node = {
key,
value,
newer: null,
older: this.newest,
};
if (this.newest) {
this.newest.newer = node;
}
this.newest = node;
this.oldest = this.oldest || node;
this.scheduleFinalization(node);
this.map.set(key, node);
this.size++;
return node.value;
}
clean() {
while (this.oldest && this.size > this.max) {
this.deleteNode(this.oldest);
}
}
deleteNode(node) {
if (node === this.newest) {
this.newest = node.older;
}
if (node === this.oldest) {
this.oldest = node.newer;
}
if (node.newer) {
node.newer.older = node.older;
}
if (node.older) {
node.older.newer = node.newer;
}
this.size--;
const key = node.key || (node.keyRef && node.keyRef.deref());
this.dispose(node.value, key);
if (!node.keyRef) {
this.unfinalizedNodes.delete(node);
}
else {
this.registry.unregister(node);
}
if (key)
this.map.delete(key);
}
delete(key) {
const node = this.map.get(key);
if (node) {
this.deleteNode(node);
return true;
}
return false;
}
scheduleFinalization(node) {
this.unfinalizedNodes.add(node);
if (!this.finalizationScheduled) {
this.finalizationScheduled = true;
queueMicrotask(this.finalize);
}
}
}
//# sourceMappingURL=weak.js.map

1
node_modules/@wry/caches/lib/weak.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"weak.js","sourceRoot":"","sources":["../src/weak.ts"],"names":[],"mappings":"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"}

41
node_modules/@wry/caches/package.json generated vendored Normal file
View File

@@ -0,0 +1,41 @@
{
"name": "@wry/caches",
"version": "1.0.1",
"author": "Ben Newman <ben@eloper.dev>",
"description": "Various cache implementations",
"license": "MIT",
"type": "module",
"sideEffects": false,
"main": "lib/bundle.cjs",
"module": "lib/index.js",
"types": "lib/index.d.ts",
"keywords": [],
"homepage": "https://github.com/benjamn/wryware",
"repository": {
"type": "git",
"url": "git+https://github.com/benjamn/wryware.git"
},
"bugs": {
"url": "https://github.com/benjamn/wryware/issues"
},
"scripts": {
"build": "npm run clean:before && npm run tsc && npm run rollup && npm run clean:after",
"clean:before": "rimraf lib",
"tsc": "npm run tsc:es5 && npm run tsc:esm",
"tsc:es5": "tsc -p tsconfig.es5.json",
"tsc:esm": "tsc -p tsconfig.json",
"rollup": "rollup -c rollup.config.js",
"clean:after": "rimraf lib/es5",
"prepare": "npm run build",
"test:cjs": "../../shared/test.sh lib/tests/bundle.cjs",
"test:esm": "../../shared/test.sh lib/tests/bundle.js",
"test": "npm run test:esm && npm run test:cjs"
},
"dependencies": {
"tslib": "^2.3.0"
},
"engines": {
"node": ">=8"
},
"gitHead": "fc1400e8db54eb763822c69748c866909363a2c3"
}

1
node_modules/@wry/caches/rollup.config.js generated vendored Normal file
View File

@@ -0,0 +1 @@
export { default } from "../../shared/rollup.config.js";

8
node_modules/@wry/caches/src/common.ts generated vendored Normal file
View File

@@ -0,0 +1,8 @@
export interface CommonCache<K, V> {
has(key: K): boolean;
get(key: K): V | undefined;
set(key: K, value: V): V;
delete(key: K): boolean;
clean(): void;
readonly size: number;
}

3
node_modules/@wry/caches/src/index.ts generated vendored Normal file
View File

@@ -0,0 +1,3 @@
export type { CommonCache } from "./common.js";
export { StrongCache } from "./strong.js";
export { WeakCache } from "./weak.js";

121
node_modules/@wry/caches/src/strong.ts generated vendored Normal file
View File

@@ -0,0 +1,121 @@
import type { CommonCache } from "./common";
interface Node<K, V> {
key: K;
value: V;
newer: Node<K, V> | null;
older: Node<K, V> | null;
}
function defaultDispose() {}
export class StrongCache<K = any, V = any> implements CommonCache<K, V> {
private map = new Map<K, Node<K, V>>();
private newest: Node<K, V> | null = null;
private oldest: Node<K, V> | null = null;
constructor(
private max = Infinity,
public dispose: (value: V, key: K) => void = defaultDispose,
) {}
public has(key: K): boolean {
return this.map.has(key);
}
public get(key: K): V | undefined {
const node = this.getNode(key);
return node && node.value;
}
public get size() {
return this.map.size;
}
private getNode(key: K): Node<K, V> | undefined {
const node = this.map.get(key);
if (node && node !== this.newest) {
const { older, newer } = node;
if (newer) {
newer.older = older;
}
if (older) {
older.newer = newer;
}
node.older = this.newest;
node.older!.newer = node;
node.newer = null;
this.newest = node;
if (node === this.oldest) {
this.oldest = newer;
}
}
return node;
}
public set(key: K, value: V): V {
let node = this.getNode(key);
if (node) {
return node.value = value;
}
node = {
key,
value,
newer: null,
older: this.newest
};
if (this.newest) {
this.newest.newer = node;
}
this.newest = node;
this.oldest = this.oldest || node;
this.map.set(key, node);
return node.value;
}
public clean() {
while (this.oldest && this.map.size > this.max) {
this.delete(this.oldest.key);
}
}
public delete(key: K): boolean {
const node = this.map.get(key);
if (node) {
if (node === this.newest) {
this.newest = node.older;
}
if (node === this.oldest) {
this.oldest = node.newer;
}
if (node.newer) {
node.newer.older = node.older;
}
if (node.older) {
node.older.newer = node.newer;
}
this.map.delete(key);
this.dispose(node.value, key);
return true;
}
return false;
}
}

2
node_modules/@wry/caches/src/tests/main.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
import "./strong.js";
import "./weak.js";

108
node_modules/@wry/caches/src/tests/strong.ts generated vendored Normal file
View File

@@ -0,0 +1,108 @@
import * as assert from "assert";
import { StrongCache } from "../strong.js";
describe("least-recently-used cache", function () {
it("can hold lots of elements", function () {
const cache = new StrongCache;
const count = 1000000;
for (let i = 0; i < count; ++i) {
cache.set(i, String(i));
}
cache.clean();
assert.strictEqual((cache as any).map.size, count);
assert.ok(cache.has(0));
assert.ok(cache.has(count - 1));
assert.strictEqual(cache.get(43), "43");
});
it("evicts excess old elements", function () {
const max = 10;
const evicted = [];
const cache = new StrongCache(max, (value, key) => {
assert.strictEqual(String(key), value);
evicted.push(key);
});
const count = 100;
const keys = [];
for (let i = 0; i < count; ++i) {
cache.set(i, String(i));
keys.push(i);
}
cache.clean();
assert.strictEqual((cache as any).map.size, max);
assert.strictEqual(evicted.length, count - max);
for (let i = count - max; i < count; ++i) {
assert.ok(cache.has(i));
}
});
it("can cope with small max values", function () {
const cache = new StrongCache(2);
function check(...sequence: number[]) {
cache.clean();
let entry = (cache as any).newest;
const forwards = [];
while (entry) {
forwards.push(entry.key);
entry = entry.older;
}
assert.deepEqual(forwards, sequence);
const backwards = [];
entry = (cache as any).oldest;
while (entry) {
backwards.push(entry.key);
entry = entry.newer;
}
backwards.reverse();
assert.deepEqual(backwards, sequence);
sequence.forEach(function (n) {
assert.strictEqual((cache as any).map.get(n).value, n + 1);
});
if (sequence.length > 0) {
assert.strictEqual((cache as any).newest.key, sequence[0]);
assert.strictEqual((cache as any).oldest.key,
sequence[sequence.length - 1]);
}
}
cache.set(1, 2);
check(1);
cache.set(2, 3);
check(2, 1);
cache.set(3, 4);
check(3, 2);
cache.get(2);
check(2, 3);
cache.set(4, 5);
check(4, 2);
assert.strictEqual(cache.has(1), false);
assert.strictEqual(cache.get(2), 3);
assert.strictEqual(cache.has(3), false);
assert.strictEqual(cache.get(4), 5);
cache.delete(2);
check(4);
cache.delete(4);
check();
assert.strictEqual((cache as any).newest, null);
assert.strictEqual((cache as any).oldest, null);
});
});

170
node_modules/@wry/caches/src/tests/weak.ts generated vendored Normal file
View File

@@ -0,0 +1,170 @@
import * as assert from "assert";
import { WeakCache } from "../weak.js";
describe("weak least-recently-used cache", function () {
it("can hold lots of elements", async function () {
this.timeout(10000);
const cache = new WeakCache();
const count = 1000000;
const keys = [];
for (let i = 0; i < count; ++i) {
const key = {};
cache.set(key, String(i));
keys[i] = key;
}
await waitForCache(cache);
cache.clean();
assert.strictEqual(cache.size, count);
assert.ok(cache.has(keys[0]));
assert.ok(cache.has(keys[count - 1]));
assert.strictEqual(cache.get(keys[43]), "43");
});
it("evicts excess old elements", function () {
const max = 10;
const evicted = [];
const cache = new WeakCache(max, (value, key) => {
assert.strictEqual(key.valueOf(), value.valueOf());
evicted.push(key);
});
const count = 100;
const keys = [];
for (let i = 0; i < count; ++i) {
const key = new String(i);
cache.set(key, String(i));
keys[i] = key;
}
cache.clean();
assert.strictEqual((cache as any).size, max);
assert.strictEqual(evicted.length, count - max);
for (let i = count - max; i < count; ++i) {
assert.ok(cache.has(keys[i]));
}
});
it("evicts elements that are garbage collected", async function () {
const cache = new WeakCache();
const count = 100;
const keys: Array<String | null> = [];
for (let i = 0; i < count; ++i) {
keys[i] = new String(i);
cache.set(keys[i], String(i));
}
assert.strictEqual(cache.size, 100);
await waitForCache(cache);
assert.strictEqual(cache.size, 100);
for (let i = 0; i < 50; ++i) {
keys[i] = null;
}
return gcPromise(() => {
return cache.size > 50 ? null : () => {
assert.strictEqual(cache.size, 50);
assert.strictEqual(keys.length, 100);
assert.strictEqual(new Set(keys).size, 51);
};
});
});
function gcPromise(test: () => null | (() => void)) {
return new Promise<void>(function (resolve, reject) {
function pollGC() {
global.gc!();
const testCallback = test();
if (!testCallback) {
setTimeout(pollGC, 20);
} else try {
testCallback();
resolve();
} catch (e) {
reject(e);
}
}
pollGC();
});
}
it("can cope with small max values", async function () {
const cache = new WeakCache(2);
const keys = Array(10)
.fill(null)
.map((_, i) => new Number(i));
async function check(...sequence: number[]) {
await waitForCache(cache);
cache.clean();
let entry = cache["newest"];
const forwards = [];
while (entry) {
forwards.push(entry.keyRef?.deref());
entry = entry.older;
}
assert.deepEqual(forwards.map(Number), sequence);
const backwards = [];
entry = cache["oldest"];
while (entry) {
backwards.push(entry.keyRef?.deref());
entry = entry.newer;
}
backwards.reverse();
assert.deepEqual(backwards.map(Number), sequence);
sequence.forEach(function (n) {
assert.strictEqual(cache["map"].get(keys[n])?.value, n + 1);
});
if (sequence.length > 0) {
assert.strictEqual(
cache["oldest"]?.keyRef?.deref().valueOf(),
sequence[sequence.length - 1]
);
}
}
cache.set(keys[1], 2);
await check(1);
cache.set(keys[2], 3);
await check(2, 1);
cache.set(keys[3], 4);
await check(3, 2);
cache.get(keys[2]);
await check(2, 3);
cache.set(keys[4], 5);
await check(4, 2);
assert.strictEqual(cache.has(keys[1]), false);
assert.strictEqual(cache.get(keys[2]), 3);
assert.strictEqual(cache.has(keys[3]), false);
assert.strictEqual(cache.get(keys[4]), 5);
cache.delete(keys[2]);
await check(4);
cache.delete(keys[4]);
await check();
assert.strictEqual((cache as any).newest, null);
assert.strictEqual((cache as any).oldest, null);
});
});
async function waitForCache(cache: WeakCache) {
while (cache["finalizationScheduled"]) {
await new Promise<void>(queueMicrotask);
}
}

200
node_modules/@wry/caches/src/weak.ts generated vendored Normal file
View File

@@ -0,0 +1,200 @@
import type { CommonCache } from "./common";
interface PartialNode<K extends object, V> {
value: V;
newer: Node<K, V> | null;
older: Node<K, V> | null;
}
interface UnfinalizedNode<K extends object, V> extends PartialNode<K, V> {
keyRef?: undefined;
key: K;
}
interface FullNode<K extends object, V> extends PartialNode<K, V> {
keyRef: WeakRef<K>;
key?: undefined;
}
type Node<K extends object, V> = FullNode<K, V> | UnfinalizedNode<K, V>;
function noop() {}
const defaultDispose = noop;
const _WeakRef =
typeof WeakRef !== "undefined"
? WeakRef
: (function <T>(value: T) {
return { deref: () => value } satisfies Omit<
WeakRef<any>,
typeof Symbol.toStringTag
>;
} as any as typeof WeakRef);
const _WeakMap = typeof WeakMap !== "undefined" ? WeakMap : Map;
const _FinalizationRegistry =
typeof FinalizationRegistry !== "undefined"
? FinalizationRegistry
: (function <T>() {
return {
register: noop,
unregister: noop,
} satisfies Omit<FinalizationRegistry<T>, typeof Symbol.toStringTag>;
} as any as typeof FinalizationRegistry);
const finalizationBatchSize = 10024;
export class WeakCache<K extends object = any, V = any>
implements CommonCache<K, V>
{
private map = new _WeakMap<K, Node<K, V>>();
private registry: FinalizationRegistry<Node<K, V>>;
private newest: Node<K, V> | null = null;
private oldest: Node<K, V> | null = null;
private unfinalizedNodes: Set<UnfinalizedNode<K, V>> = new Set();
private finalizationScheduled = false;
public size = 0;
constructor(
private max = Infinity,
public dispose: (value: V, key?: K) => void = defaultDispose
) {
this.registry = new _FinalizationRegistry<Node<K, V>>(
this.deleteNode.bind(this)
);
}
public has(key: K): boolean {
return this.map.has(key);
}
public get(key: K): V | undefined {
const node = this.getNode(key);
return node && node.value;
}
private getNode(key: K): Node<K, V> | undefined {
const node = this.map.get(key);
if (node && node !== this.newest) {
const { older, newer } = node;
if (newer) {
newer.older = older;
}
if (older) {
older.newer = newer;
}
node.older = this.newest;
node.older!.newer = node;
node.newer = null;
this.newest = node;
if (node === this.oldest) {
this.oldest = newer;
}
}
return node;
}
public set(key: K, value: V): V {
let node = this.getNode(key);
if (node) {
return (node.value = value);
}
node = {
key,
value,
newer: null,
older: this.newest,
};
if (this.newest) {
this.newest.newer = node;
}
this.newest = node;
this.oldest = this.oldest || node;
this.scheduleFinalization(node);
this.map.set(key, node);
this.size++;
return node.value;
}
public clean() {
while (this.oldest && this.size > this.max) {
this.deleteNode(this.oldest);
}
}
private deleteNode(node: Node<K, V>) {
if (node === this.newest) {
this.newest = node.older;
}
if (node === this.oldest) {
this.oldest = node.newer;
}
if (node.newer) {
node.newer.older = node.older;
}
if (node.older) {
node.older.newer = node.newer;
}
this.size--;
const key = node.key || (node.keyRef && node.keyRef.deref());
this.dispose(node.value, key);
if (!node.keyRef) {
this.unfinalizedNodes.delete(node);
} else {
this.registry.unregister(node);
}
if (key) this.map.delete(key);
}
public delete(key: K): boolean {
const node = this.map.get(key);
if (node) {
this.deleteNode(node);
return true;
}
return false;
}
private scheduleFinalization(node: UnfinalizedNode<K, V>) {
this.unfinalizedNodes.add(node);
if (!this.finalizationScheduled) {
this.finalizationScheduled = true;
queueMicrotask(this.finalize);
}
}
private finalize = () => {
const iterator = this.unfinalizedNodes.values();
for (let i = 0; i < finalizationBatchSize; i++) {
const node = iterator.next().value;
if (!node) break;
this.unfinalizedNodes.delete(node);
const key = node.key;
delete (node as unknown as FullNode<K, V>).key;
(node as unknown as FullNode<K, V>).keyRef = new _WeakRef(key);
this.registry.register(key, node, node);
}
if (this.unfinalizedNodes.size > 0) {
queueMicrotask(this.finalize);
} else {
this.finalizationScheduled = false;
}
};
}