Skip to content
Merged
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
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@
"@csstools/css-calc": "^3.1.1",
"@csstools/css-color-parser": "^4.0.2",
"@csstools/css-parser-algorithms": "^4.0.0",
"@csstools/css-tokenizer": "^4.0.0",
"lru-cache": "^11.2.7"
"@csstools/css-tokenizer": "^4.0.0"
},
"devDependencies": {
"@tanstack/vite-config": "^0.5.2",
Expand Down
3 changes: 0 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

72 changes: 61 additions & 11 deletions src/js/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* cache
*/

import { LRUCache } from 'lru-cache';
import { Options } from './typedef';

/* numeric constants */
Expand Down Expand Up @@ -45,12 +44,63 @@ export class NullObject extends CacheItem {
}
}

/**
* Generational Cache implementation
*/
export class GenerationalCache<K, V> {
private max: number;
private current: Map<K, V>;
private old: Map<K, V>;

constructor(max: number) {
this.max = Math.ceil(max / 2);
this.current = new Map<K, V>();
this.old = new Map<K, V>();
}

get(key: K): V | undefined {
let value = this.current.get(key);
if (value !== undefined) {
return value;
}

value = this.old.get(key);
if (value !== undefined) {
this.set(key, value);
return value;
}

return undefined;
}

set(key: K, value: V): void {
this.current.set(key, value);

if (this.current.size >= this.max) {
this.old = this.current;
this.current = new Map<K, V>();
}
}

has(key: K): boolean {
return this.current.has(key) || this.old.has(key);
}

delete(key: K): void {
this.current.delete(key);
this.old.delete(key);
}

clear(): void {
this.current.clear();
this.old.clear();
}
}

/*
* lru cache
* generational cache instance
*/
export const lruCache = new LRUCache({
max: MAX_CACHE
});
export const genCache = new GenerationalCache<string, CacheItem>(MAX_CACHE);

/**
* set cache
Expand All @@ -61,11 +111,11 @@ export const lruCache = new LRUCache({
export const setCache = (key: string, value: unknown): void => {
if (key) {
if (value === null) {
lruCache.set(key, new NullObject());
genCache.set(key, new NullObject());
} else if (value instanceof CacheItem) {
lruCache.set(key, value);
genCache.set(key, value);
} else {
lruCache.set(key, new CacheItem(value));
genCache.set(key, new CacheItem(value));
}
}
};
Expand All @@ -76,13 +126,13 @@ export const setCache = (key: string, value: unknown): void => {
* @returns cached item or false otherwise
*/
export const getCache = (key: string): CacheItem | boolean => {
if (key && lruCache.has(key)) {
const item = lruCache.get(key);
if (key && genCache.has(key)) {
const item = genCache.get(key);
if (item instanceof CacheItem) {
return item;
}
// delete unexpected cached item
lruCache.delete(key);
genCache.delete(key);
return false;
}
return false;
Expand Down
51 changes: 25 additions & 26 deletions test/cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,17 @@
import { afterEach, assert, beforeEach, describe, it } from 'vitest';

/* test */
import { LRUCache } from 'lru-cache';
import * as cache from '../src/js/cache';

describe('lru cache', () => {
describe('generational cache', () => {
it('should be instance', () => {
const { lruCache } = cache;
assert.strictEqual(lruCache instanceof LRUCache, true, 'instance');
assert.strictEqual(typeof lruCache.clear, 'function', 'clear');
assert.strictEqual(typeof lruCache.delete, 'function', 'delete');
assert.strictEqual(typeof lruCache.get, 'function', 'get');
assert.strictEqual(typeof lruCache.has, 'function', 'has');
assert.strictEqual(typeof lruCache.set, 'function', 'set');
const { GenerationalCache, genCache } = cache;
assert.strictEqual(genCache instanceof GenerationalCache, true, 'instance');
assert.strictEqual(typeof genCache.clear, 'function', 'clear');
assert.strictEqual(typeof genCache.delete, 'function', 'delete');
assert.strictEqual(typeof genCache.get, 'function', 'get');
assert.strictEqual(typeof genCache.has, 'function', 'has');
assert.strictEqual(typeof genCache.set, 'function', 'set');
});
});

Expand Down Expand Up @@ -58,55 +57,55 @@ describe('NullObject', () => {
});

describe('set cache', () => {
const { CacheItem, lruCache } = cache;
const { CacheItem, genCache } = cache;
const func = cache.setCache;

beforeEach(() => {
lruCache.clear();
genCache.clear();
});
afterEach(() => {
lruCache.clear();
genCache.clear();
});

it('should not set cache', () => {
func('');
assert.strictEqual(lruCache.has(''), false, 'has');
assert.strictEqual(genCache.has(''), false, 'has');
});

it('should set cache', () => {
func('foo');
assert.strictEqual(lruCache.has('foo'), true, 'has');
assert.strictEqual(lruCache.get('foo') instanceof CacheItem, true, 'cache');
assert.strictEqual(genCache.has('foo'), true, 'has');
assert.strictEqual(genCache.get('foo') instanceof CacheItem, true, 'cache');
});

it('should set cache', () => {
func('bar', 'bar');
assert.strictEqual(lruCache.has('bar'), true, 'has');
assert.strictEqual(lruCache.get('bar') instanceof CacheItem, true, 'cache');
assert.strictEqual(genCache.has('bar'), true, 'has');
assert.strictEqual(genCache.get('bar') instanceof CacheItem, true, 'cache');
});

it('should set cache', () => {
func('baz', null);
assert.strictEqual(lruCache.has('baz'), true, 'has');
assert.strictEqual(lruCache.get('baz') instanceof CacheItem, true, 'cache');
assert.strictEqual(genCache.has('baz'), true, 'has');
assert.strictEqual(genCache.get('baz') instanceof CacheItem, true, 'cache');
});

it('should set cache', () => {
func('qux', new CacheItem('qux'));
assert.strictEqual(lruCache.has('qux'), true, 'has');
assert.strictEqual(lruCache.get('qux') instanceof CacheItem, true, 'cache');
assert.strictEqual(genCache.has('qux'), true, 'has');
assert.strictEqual(genCache.get('qux') instanceof CacheItem, true, 'cache');
});
});

describe('get cache', () => {
const { CacheItem, NullObject, lruCache, setCache } = cache;
const { CacheItem, NullObject, genCache, setCache } = cache;
const func = cache.getCache;

beforeEach(() => {
lruCache.clear();
genCache.clear();
});
afterEach(() => {
lruCache.clear();
genCache.clear();
});

it('should get cache', () => {
Expand Down Expand Up @@ -138,9 +137,9 @@ describe('get cache', () => {
});

it('should get false and delete key', () => {
lruCache.set('quux', 'quux');
genCache.set('quux', 'quux');
const res = func('quux');
assert.strictEqual(lruCache.has('quux'), false, 'key');
assert.strictEqual(genCache.has('quux'), false, 'key');
assert.strictEqual(res, false, 'result');
});
});
Expand Down
6 changes: 3 additions & 3 deletions test/color.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
import { afterEach, assert, beforeEach, describe, it } from 'vitest';

/* test */
import { NullObject, lruCache } from '../src/js/cache';
import { NullObject, genCache } from '../src/js/cache';
import * as color from '../src/js/color';

beforeEach(() => {
lruCache.clear();
genCache.clear();
});
afterEach(() => {
lruCache.clear();
genCache.clear();
});

describe('cache invalid color value', () => {
Expand Down
6 changes: 3 additions & 3 deletions test/convert.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import { afterEach, assert, beforeEach, describe, it } from 'vitest';

/* test */
import * as convert from '../src/js/convert.js';
import { lruCache } from '../src/js/cache.js';
import { genCache } from '../src/js/cache.js';

beforeEach(() => {
lruCache.clear();
genCache.clear();
});

afterEach(() => {
lruCache.clear();
genCache.clear();
});

describe('pre process', () => {
Expand Down
6 changes: 3 additions & 3 deletions test/css-calc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
import { afterEach, assert, beforeEach, describe, it } from 'vitest';

/* test */
import { lruCache } from '../src/js/cache';
import { genCache } from '../src/js/cache';
import * as csscalc from '../src/js/css-calc';

beforeEach(() => {
lruCache.clear();
genCache.clear();
});

afterEach(() => {
lruCache.clear();
genCache.clear();
});

describe('Calculator', () => {
Expand Down
6 changes: 3 additions & 3 deletions test/css-gradient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
import { afterEach, assert, beforeEach, describe, it } from 'vitest';

/* test */
import { lruCache } from '../src/js/cache';
import { genCache } from '../src/js/cache';
import * as grad from '../src/js/css-gradient';

beforeEach(() => {
lruCache.clear();
genCache.clear();
});

afterEach(() => {
lruCache.clear();
genCache.clear();
});

describe('get gradient type', () => {
Expand Down
6 changes: 3 additions & 3 deletions test/css-var.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
import { afterEach, assert, beforeEach, describe, it } from 'vitest';

/* test */
import { lruCache } from '../src/js/cache';
import { genCache } from '../src/js/cache';
import * as custom from '../src/js/css-var';

beforeEach(() => {
lruCache.clear();
genCache.clear();
});

afterEach(() => {
lruCache.clear();
genCache.clear();
});

describe('resolve CSS variable', () => {
Expand Down
6 changes: 3 additions & 3 deletions test/relative-color.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import { tokenize } from '@csstools/css-tokenizer';
import { afterEach, assert, beforeEach, describe, it } from 'vitest';

/* test */
import { lruCache } from '../src/js/cache';
import { genCache } from '../src/js/cache';
import * as relColor from '../src/js/relative-color';

beforeEach(() => {
lruCache.clear();
genCache.clear();
});

afterEach(() => {
lruCache.clear();
genCache.clear();
});

describe('resolve relative color channels', () => {
Expand Down
6 changes: 3 additions & 3 deletions test/resolve.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import { afterEach, assert, beforeEach, describe, it } from 'vitest';

/* test */
import * as api from '../src/js/resolve';
import { lruCache } from '../src/js/cache';
import { genCache } from '../src/js/cache';
import { parseColorValue } from '../src/js/color';

beforeEach(() => {
lruCache.clear();
genCache.clear();
});

afterEach(() => {
lruCache.clear();
genCache.clear();
});

describe('resolve CSS color', () => {
Expand Down
6 changes: 3 additions & 3 deletions test/util.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
import { afterEach, assert, beforeEach, describe, it } from 'vitest';

/* test */
import { lruCache } from '../src/js/cache';
import { genCache } from '../src/js/cache';
import * as util from '../src/js/util';

beforeEach(() => {
lruCache.clear();
genCache.clear();
});

afterEach(() => {
lruCache.clear();
genCache.clear();
});

describe('split value', () => {
Expand Down
Loading