cspell-dictionary 8.11.0 → 8.13.0

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.
@@ -21,6 +21,17 @@ export interface CachingDictionary {
21
21
  stats(): CallStats;
22
22
  getPreferredSuggestions(word: string): PreferredSuggestion[] | undefined;
23
23
  }
24
+ interface LogEntryBase extends SearchOptions {
25
+ time: number;
26
+ method: 'has';
27
+ word: string;
28
+ value?: unknown;
29
+ }
30
+ interface LogEntryHas extends LogEntryBase {
31
+ method: 'has';
32
+ value: boolean;
33
+ }
34
+ export type LogEntry = LogEntryHas;
24
35
  /**
25
36
  * create a caching dictionary
26
37
  * @param dict - Dictionary to cache the search results.
@@ -28,5 +39,7 @@ export interface CachingDictionary {
28
39
  * @returns CachingDictionary
29
40
  */
30
41
  export declare function createCachingDictionary(dict: SpellingDictionary | SpellingDictionaryCollection, options: SearchOptions): CachingDictionary;
42
+ export declare function enableLogging(enabled?: boolean): void;
43
+ export declare function getLog(): LogEntryBase[];
31
44
  export {};
32
45
  //# sourceMappingURL=CachingDictionary.d.ts.map
@@ -2,6 +2,9 @@ import { autoCache, extractStats } from '../util/AutoCache.js';
2
2
  import { canonicalSearchOptions } from './SpellingDictionaryMethods.js';
3
3
  let dictionaryCounter = 0;
4
4
  const DefaultAutoCacheSize = 1000;
5
+ let logRequests = false;
6
+ const log = [];
7
+ const startTime = performance.now();
5
8
  class CachedDict {
6
9
  dict;
7
10
  options;
@@ -13,7 +16,15 @@ class CachedDict {
13
16
  this.name = dict.name;
14
17
  // console.log(`CachedDict for ${this.name}`);
15
18
  }
16
- has = autoCache((word) => this.dict.has(word, this.options), DefaultAutoCacheSize);
19
+ #has = autoCache((word) => this.dict.has(word, this.options), DefaultAutoCacheSize);
20
+ has = logRequests
21
+ ? (word) => {
22
+ const time = performance.now() - startTime;
23
+ const value = this.#has(word);
24
+ log.push({ time, method: 'has', word, value });
25
+ return value;
26
+ }
27
+ : this.#has;
17
28
  isNoSuggestWord = autoCache((word) => this.dict.isNoSuggestWord(word, this.options), DefaultAutoCacheSize);
18
29
  isForbidden = autoCache((word) => this.dict.isForbidden(word), DefaultAutoCacheSize);
19
30
  getPreferredSuggestions = autoCache((word) => this.dict.getPreferredSuggestions?.(word), DefaultAutoCacheSize);
@@ -21,7 +32,7 @@ class CachedDict {
21
32
  return {
22
33
  name: this.name,
23
34
  id: this.id,
24
- has: extractStats(this.has),
35
+ has: extractStats(this.#has),
25
36
  isNoSuggestWord: extractStats(this.isNoSuggestWord),
26
37
  isForbidden: extractStats(this.isForbidden),
27
38
  getPreferredSuggestions: extractStats(this.getPreferredSuggestions),
@@ -49,4 +60,10 @@ export function createCachingDictionary(dict, options) {
49
60
  knownOptions.set(dict, cached);
50
61
  return cached;
51
62
  }
63
+ export function enableLogging(enabled = !logRequests) {
64
+ logRequests = enabled;
65
+ }
66
+ export function getLog() {
67
+ return log;
68
+ }
52
69
  //# sourceMappingURL=CachingDictionary.js.map
@@ -1,5 +1,4 @@
1
1
  import { CASE_INSENSITIVE_PREFIX, CompoundWordsMethod } from 'cspell-trie-lib';
2
- import { genSequence } from 'gensequence';
3
2
  import { isDefined } from '../util/util.js';
4
3
  import * as Defaults from './defaults.js';
5
4
  import { defaultNumSuggestions, hasOptionToSearchOption, suggestionCollector } from './SpellingDictionaryMethods.js';
@@ -98,7 +97,7 @@ export function createCollection(dictionaries, name, source) {
98
97
  return new SpellingDictionaryCollectionImpl(dictionaries, name, source);
99
98
  }
100
99
  function isWordInAnyDictionary(dicts, word, options) {
101
- return genSequence(dicts).first((dict) => dict.has(word, options));
100
+ return dicts.find((dict) => dict.has(word, options));
102
101
  }
103
102
  function findInAnyDictionary(dicts, word, options) {
104
103
  const found = dicts.map((dict) => dict.find(word, options)).filter(isDefined);
@@ -111,10 +110,10 @@ function findInAnyDictionary(dicts, word, options) {
111
110
  }));
112
111
  }
113
112
  function isNoSuggestWordInAnyDictionary(dicts, word, options) {
114
- return genSequence(dicts).first((dict) => dict.isNoSuggestWord(word, options));
113
+ return dicts.find((dict) => dict.isNoSuggestWord(word, options));
115
114
  }
116
115
  function isWordForbiddenInAnyDictionary(dicts, word, ignoreCase) {
117
- return genSequence(dicts).first((dict) => dict.isForbidden(word, ignoreCase));
116
+ return dicts.find((dict) => dict.isForbidden(word, ignoreCase));
118
117
  }
119
118
  export function isSpellingDictionaryCollection(dict) {
120
119
  return dict instanceof SpellingDictionaryCollectionImpl;
@@ -6,7 +6,6 @@ export declare class SpellingDictionaryFromTrie implements SpellingDictionary {
6
6
  readonly name: string;
7
7
  readonly options: SpellingDictionaryOptions;
8
8
  readonly source: string;
9
- static readonly cachedWordsLimit = 50000;
10
9
  private _size;
11
10
  readonly knownWords: Set<string>;
12
11
  readonly unknownWords: Set<string>;
@@ -26,7 +25,6 @@ export declare class SpellingDictionaryFromTrie implements SpellingDictionary {
26
25
  private _findAnyForm;
27
26
  isNoSuggestWord(word: string, options?: HasOptions): boolean;
28
27
  isForbidden(word: string, _ignoreCaseAndAccents?: boolean): boolean;
29
- private _isForbidden;
30
28
  suggest(word: string, suggestOptions?: SuggestOptions): SuggestionResult[];
31
29
  private _suggest;
32
30
  genSuggestions(collector: SuggestionCollector, suggestOptions: SuggestOptions): void;
@@ -1,5 +1,4 @@
1
1
  import { CompoundWordsMethod, decodeTrie, suggestionCollector } from 'cspell-trie-lib';
2
- import { autoCache, createCache01 } from '../util/AutoCache.js';
3
2
  import { clean } from '../util/clean.js';
4
3
  import { createMapper, createRepMapper } from '../util/repMap.js';
5
4
  import * as Defaults from './defaults.js';
@@ -11,7 +10,6 @@ export class SpellingDictionaryFromTrie {
11
10
  name;
12
11
  options;
13
12
  source;
14
- static cachedWordsLimit = 50_000;
15
13
  _size = 0;
16
14
  knownWords = new Set();
17
15
  unknownWords = new Set();
@@ -68,7 +66,7 @@ export class SpellingDictionaryFromTrie {
68
66
  const { useCompounds = this.options.useCompounds, ignoreCase = Defaults.ignoreCase } = hasOptionToSearchOption(hasOptions);
69
67
  return { useCompounds, ignoreCase };
70
68
  }
71
- _find = findCache((word, useCompounds, ignoreCase) => this.findAnyForm(word, useCompounds, ignoreCase));
69
+ _find = (word, useCompounds, ignoreCase) => this.findAnyForm(word, useCompounds, ignoreCase);
72
70
  findAnyForm(word, useCompounds, ignoreCase) {
73
71
  const outerForms = outerWordForms(word, this.remapWord || ((word) => [this.mapWord(word)]));
74
72
  for (const form of outerForms) {
@@ -106,11 +104,8 @@ export class SpellingDictionaryFromTrie {
106
104
  return this.containsNoSuggestWords ? this.has(word, options) : false;
107
105
  }
108
106
  isForbidden(word, _ignoreCaseAndAccents) {
109
- return this._isForbidden(word);
110
- }
111
- _isForbidden = autoCache((word) => {
112
107
  return this.trie.isForbiddenWord(word);
113
- });
108
+ }
114
109
  suggest(word, suggestOptions = {}) {
115
110
  return this._suggest(word, suggestOptions);
116
111
  }
@@ -154,38 +149,29 @@ export function createSpellingDictionaryFromTrieFile(data, name, source, options
154
149
  const trie = decodeTrie(data);
155
150
  return new SpellingDictionaryFromTrie(trie, name, options, source);
156
151
  }
157
- function findCache(fn, size = 2000) {
158
- const cache = createCache01(size);
159
- function find(word, useCompounds, ignoreCase) {
160
- const r = cache.get(word);
161
- if (r !== undefined && r.useCompounds === useCompounds && r.ignoreCase === ignoreCase) {
162
- return r.findResult;
163
- }
164
- const findResult = fn(word, useCompounds, ignoreCase);
165
- cache.set(word, { useCompounds, ignoreCase, findResult });
166
- return findResult;
167
- }
168
- return find;
169
- }
170
152
  function* outerWordForms(word, mapWord) {
171
153
  // Only generate the needed forms.
172
154
  const sent = new Set();
173
155
  let w = word;
156
+ const ww = w;
174
157
  yield w;
175
158
  sent.add(w);
176
159
  w = word.normalize('NFC');
177
- if (!sent.has(w))
160
+ if (w !== ww) {
178
161
  yield w;
179
- sent.add(w);
162
+ sent.add(w);
163
+ }
180
164
  w = word.normalize('NFD');
181
- if (!sent.has(w))
165
+ if (w !== ww && !sent.has(w)) {
182
166
  yield w;
183
- sent.add(w);
184
- for (const f of [...sent]) {
167
+ sent.add(w);
168
+ }
169
+ for (const f of sent) {
185
170
  for (const m of mapWord(f)) {
186
- if (!sent.has(m))
171
+ if (m !== ww && !sent.has(m)) {
187
172
  yield m;
188
- sent.add(m);
173
+ sent.add(m);
174
+ }
189
175
  }
190
176
  }
191
177
  return;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,11 @@
1
+ import { enableLogging as cacheDictionaryEnableLogging, getLog as cacheDictionaryGetLog } from './SpellingDictionary/CachingDictionary.js';
1
2
  export type { CachingDictionary, FindOptions, FindResult, HasOptions, SearchOptions, SpellingDictionary, SpellingDictionaryCollection, SpellingDictionaryOptions, SuggestionCollector, SuggestionResult, SuggestOptions, } from './SpellingDictionary/index.js';
2
3
  export { createCachingDictionary, createCollection, createFailedToLoadDictionary, createFlagWordsDictionary, createForbiddenWordsDictionary, createIgnoreWordsDictionary, createInlineSpellingDictionary, createSpellingDictionary, createSpellingDictionaryFromTrieFile, createSuggestDictionary, createSuggestOptions, } from './SpellingDictionary/index.js';
4
+ /**
5
+ * Debugging utilities.
6
+ */
7
+ export declare const _debug: {
8
+ cacheDictionaryEnableLogging: typeof cacheDictionaryEnableLogging;
9
+ cacheDictionaryGetLog: typeof cacheDictionaryGetLog;
10
+ };
3
11
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,2 +1,10 @@
1
+ import { enableLogging as cacheDictionaryEnableLogging, getLog as cacheDictionaryGetLog, } from './SpellingDictionary/CachingDictionary.js';
1
2
  export { createCachingDictionary, createCollection, createFailedToLoadDictionary, createFlagWordsDictionary, createForbiddenWordsDictionary, createIgnoreWordsDictionary, createInlineSpellingDictionary, createSpellingDictionary, createSpellingDictionaryFromTrieFile, createSuggestDictionary, createSuggestOptions, } from './SpellingDictionary/index.js';
3
+ /**
4
+ * Debugging utilities.
5
+ */
6
+ export const _debug = {
7
+ cacheDictionaryEnableLogging,
8
+ cacheDictionaryGetLog,
9
+ };
2
10
  //# sourceMappingURL=index.js.map
@@ -2,26 +2,41 @@ import assert from 'node:assert';
2
2
  import { buildITrieFromWords } from 'cspell-trie-lib';
3
3
  import { loremIpsum } from 'lorem-ipsum';
4
4
  import { suite } from 'perf-insight';
5
+ import { createCachingDictionary } from '../SpellingDictionary/CachingDictionary.js';
5
6
  import { createSpellingDictionary } from '../SpellingDictionary/createSpellingDictionary.js';
6
7
  import { createCollection } from '../SpellingDictionary/SpellingDictionaryCollection.js';
7
8
  suite('dictionary has', async (test) => {
8
- const words = genWords(10_000);
9
+ const words1 = genWords(10_000);
9
10
  const words2 = genWords(1000);
10
11
  const words3 = genWords(1000);
11
- const iTrie = buildITrieFromWords(words);
12
- const dict = createSpellingDictionary(words, 'test', import.meta.url);
12
+ const words = words1;
13
+ const iTrie = buildITrieFromWords(words1);
14
+ const dict = createSpellingDictionary(words1, 'test', import.meta.url);
13
15
  const dict2 = createSpellingDictionary(words2, 'test2', import.meta.url);
14
16
  const dict3 = createSpellingDictionary(words3, 'test3', import.meta.url);
15
17
  const dictCol = createCollection([dict, dict2, dict3], 'test-collection');
16
- test('dictionary has 100k words', () => {
17
- checkWords(dict, words);
18
+ const dictColRev = createCollection([dict3, dict2, dict], 'test-collection-reverse');
19
+ const cacheDictSingle = createCachingDictionary(dict, {});
20
+ const cacheDictCol = createCachingDictionary(dictCol, {});
21
+ const dictSet = new Set(words);
22
+ test('Set has 100k words', () => {
23
+ checkWords(dictSet, words);
18
24
  });
19
- test('dictionary has 100k words (2nd time)', () => {
25
+ test('dictionary has 100k words', () => {
20
26
  checkWords(dict, words);
21
27
  });
22
28
  test('collection has 100k words', () => {
23
29
  checkWords(dictCol, words);
24
30
  });
31
+ test('collection reverse has 100k words', () => {
32
+ checkWords(dictColRev, words);
33
+ });
34
+ test('cache dictionary has 100k words', () => {
35
+ checkWords(cacheDictSingle, words);
36
+ });
37
+ test('cache collection has 100k words', () => {
38
+ checkWords(cacheDictCol, words);
39
+ });
25
40
  test('iTrie has 100k words', () => {
26
41
  checkWords(iTrie, words);
27
42
  });
@@ -43,24 +58,98 @@ suite('dictionary has Not', async (test) => {
43
58
  const dict2 = createSpellingDictionary(words2, 'test2', import.meta.url);
44
59
  const dict3 = createSpellingDictionary(words3, 'test3', import.meta.url);
45
60
  const dictCol = createCollection([dict, dict2, dict3], 'test-collection');
46
- test('dictionary has 100k words', () => {
61
+ const dictSet = new Set(words);
62
+ test('Set has not 100k words', () => {
63
+ checkWords(dictSet, missingWords, false);
64
+ });
65
+ test('dictionary has not 100k words', () => {
47
66
  checkWords(dict, missingWords, false);
48
67
  });
49
- test('dictionary has 100k words (2nd time)', () => {
68
+ test('collection has not 100k words', () => {
69
+ checkWords(dictCol, missingWords, false);
70
+ });
71
+ test('iTrie has not 100k words', () => {
72
+ checkWords(iTrie, missingWords, false);
73
+ });
74
+ test('iTrie.hasWord has not 100k words', () => {
75
+ const dict = { has: (word) => iTrie.hasWord(word, true) };
50
76
  checkWords(dict, missingWords, false);
51
77
  });
78
+ test('iTrie.data has not 100k words', () => {
79
+ checkWords(iTrie.data, missingWords, false);
80
+ });
81
+ });
82
+ suite('dictionary has sampling', async (test) => {
83
+ const words1 = genWords(10_000);
84
+ const words2 = genWords(1000);
85
+ const words3 = genWords(1000);
86
+ const sampleIdx = genSamples(100_000, words1.length);
87
+ const wordsSample = sampleIdx.map((i) => words1[i]);
88
+ const iTrie = buildITrieFromWords(words1);
89
+ const dict = createSpellingDictionary(words1, 'test', import.meta.url);
90
+ const dict2 = createSpellingDictionary(words2, 'test2', import.meta.url);
91
+ const dict3 = createSpellingDictionary(words3, 'test3', import.meta.url);
92
+ const dictCol = createCollection([dict, dict2, dict3], 'test-collection');
93
+ const dictColRev = createCollection([dict3, dict2, dict], 'test-collection-reverse');
94
+ const cacheDictSingle = createCachingDictionary(dict, {});
95
+ const cacheDictCol = createCachingDictionary(dictCol, {});
96
+ const dictSet = new Set(words1);
97
+ test('Set has 100k words', () => {
98
+ checkWords(dictSet, wordsSample);
99
+ });
100
+ test('dictionary has 100k words', () => {
101
+ checkWords(dict, wordsSample);
102
+ });
52
103
  test('collection has 100k words', () => {
53
- checkWords(dictCol, missingWords, false);
104
+ checkWords(dictCol, wordsSample);
105
+ });
106
+ test('collection reverse has 100k words', () => {
107
+ checkWords(dictColRev, wordsSample);
108
+ });
109
+ test('cache dictionary has 100k words', () => {
110
+ checkWords(cacheDictSingle, wordsSample);
111
+ });
112
+ test('cache collection has 100k words', () => {
113
+ checkWords(cacheDictCol, wordsSample);
54
114
  });
55
115
  test('iTrie has 100k words', () => {
56
- checkWords(iTrie, missingWords, false);
116
+ checkWords(iTrie, wordsSample);
57
117
  });
58
118
  test('iTrie.hasWord has 100k words', () => {
59
119
  const dict = { has: (word) => iTrie.hasWord(word, true) };
60
- checkWords(dict, missingWords, false);
120
+ checkWords(dict, wordsSample);
61
121
  });
62
122
  test('iTrie.data has 100k words', () => {
63
- checkWords(iTrie.data, missingWords, false);
123
+ checkWords(iTrie.data, wordsSample);
124
+ });
125
+ });
126
+ suite('dictionary isForbidden sampling', async (test) => {
127
+ const words1 = genWords(10_000);
128
+ const words2 = genWords(1000);
129
+ const words3 = genWords(1000);
130
+ const sampleIdx = genSamples(100_000, words1.length);
131
+ const wordsSample = sampleIdx.map((i) => words1[i]);
132
+ const dict = createSpellingDictionary(words1, 'test', import.meta.url);
133
+ const dict2 = createSpellingDictionary(words2, 'test2', import.meta.url);
134
+ const dict3 = createSpellingDictionary(words3, 'test3', import.meta.url);
135
+ const dictCol = createCollection([dict, dict2, dict3], 'test-collection');
136
+ const dictColRev = createCollection([dict3, dict2, dict], 'test-collection-reverse');
137
+ const cacheDictSingle = createCachingDictionary(dict, {});
138
+ const cacheDictCol = createCachingDictionary(dictCol, {});
139
+ test('dictionary isForbidden 100k words', () => {
140
+ checkForForbiddenWords(dict, wordsSample);
141
+ });
142
+ test('collection isForbidden 100k words', () => {
143
+ checkForForbiddenWords(dictCol, wordsSample);
144
+ });
145
+ test('collection reverse isForbidden 100k words', () => {
146
+ checkForForbiddenWords(dictColRev, wordsSample);
147
+ });
148
+ test('cache dictionary isForbidden 100k words', () => {
149
+ checkForForbiddenWords(cacheDictSingle, wordsSample);
150
+ });
151
+ test('cache collection isForbidden 100k words', () => {
152
+ checkForForbiddenWords(cacheDictCol, wordsSample);
64
153
  });
65
154
  });
66
155
  function checkWords(dict, words, expected = true, totalChecks = 100_000) {
@@ -76,6 +165,16 @@ function checkWords(dict, words, expected = true, totalChecks = 100_000) {
76
165
  }
77
166
  assert(has, 'All words should be found in the dictionary');
78
167
  }
168
+ function checkForForbiddenWords(dict, words, totalChecks = 100_000) {
169
+ let result = true;
170
+ const len = words.length;
171
+ for (let i = 0; i < totalChecks; ++i) {
172
+ const word = words[i % len];
173
+ const r = !dict.isForbidden(word);
174
+ result = r && result;
175
+ }
176
+ assert(result, 'All words should not be forbidden');
177
+ }
79
178
  function genWords(count, includeForbidden = true) {
80
179
  const setOfWords = new Set(loremIpsum({ count }).split(' '));
81
180
  if (includeForbidden) {
@@ -101,4 +200,15 @@ function genWords(count, includeForbidden = true) {
101
200
  }
102
201
  return [...setOfWords];
103
202
  }
203
+ function genSamples(count, max, depth = 3) {
204
+ const r = Array(count);
205
+ for (let j = 0; j < count; ++j) {
206
+ let n = Math.random() * max;
207
+ for (let i = 1; i < depth; ++i) {
208
+ n = Math.random() * n;
209
+ }
210
+ r[j] = Math.floor(n);
211
+ }
212
+ return r;
213
+ }
104
214
  //# sourceMappingURL=has.perf.js.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=misc.perf.d.ts.map
@@ -0,0 +1,48 @@
1
+ import { genSequence } from 'gensequence';
2
+ import { loremIpsum } from 'lorem-ipsum';
3
+ import { suite } from 'perf-insight';
4
+ suite('Array Primitives', async (test) => {
5
+ const words = genWords(20);
6
+ const toFind = [...words, 'not-a-word'];
7
+ const iterations = 1000;
8
+ test('Array.find', () => {
9
+ for (let i = 0; i < iterations; ++i) {
10
+ for (const word of toFind) {
11
+ words.find((w) => w === word);
12
+ }
13
+ }
14
+ });
15
+ test('genSequence.first', () => {
16
+ for (let i = 0; i < iterations; ++i) {
17
+ for (const word of toFind) {
18
+ genSequence(words).first((w) => w === word);
19
+ }
20
+ }
21
+ });
22
+ });
23
+ function genWords(count, includeForbidden = true) {
24
+ const setOfWords = new Set(loremIpsum({ count }).split(' '));
25
+ if (includeForbidden) {
26
+ setOfWords.add('!forbidden');
27
+ setOfWords.add('!bad-word');
28
+ setOfWords.add('!rejection');
29
+ }
30
+ while (setOfWords.size < count) {
31
+ const words = [...setOfWords];
32
+ for (const a of words) {
33
+ for (const b of words) {
34
+ if (a !== b) {
35
+ setOfWords.add(a + b);
36
+ }
37
+ if (setOfWords.size >= count) {
38
+ break;
39
+ }
40
+ }
41
+ if (setOfWords.size >= count) {
42
+ break;
43
+ }
44
+ }
45
+ }
46
+ return [...setOfWords];
47
+ }
48
+ //# sourceMappingURL=misc.perf.js.map
@@ -6,17 +6,14 @@ export interface CacheStats {
6
6
  misses: number;
7
7
  swaps: number;
8
8
  }
9
- declare class Cache01<R> implements CacheStats {
9
+ declare abstract class Cache01<R> implements CacheStats {
10
10
  readonly maxSize: number;
11
- private count;
12
- private cache0;
13
- private cache1;
14
11
  hits: number;
15
12
  misses: number;
16
13
  swaps: number;
17
14
  constructor(maxSize: number);
18
- get(key: string): R | undefined;
19
- set(key: string, value: R): this;
15
+ abstract get(key: string): R | undefined;
16
+ abstract set(key: string, value: R): this;
20
17
  }
21
18
  export declare function createCache01<R>(size: number): Cache01<R>;
22
19
  export declare function autoCache<R>(fn: (p: string) => R, size?: number): AutoCache<R>;
@@ -1,46 +1,54 @@
1
1
  const CACHE_SIZE = 100;
2
2
  class Cache01 {
3
3
  maxSize;
4
- count = 0;
5
- cache0 = Object.create(null);
6
- cache1 = Object.create(null);
7
4
  hits = 0;
8
5
  misses = 0;
9
6
  swaps = 0;
10
7
  constructor(maxSize) {
11
8
  this.maxSize = maxSize;
12
9
  }
10
+ }
11
+ class Cache01Map extends Cache01 {
12
+ count = 0;
13
+ cache0 = new Map();
14
+ cache1 = new Map();
15
+ constructor(maxSize) {
16
+ super(maxSize);
17
+ }
13
18
  get(key) {
14
19
  const cache0 = this.cache0;
15
20
  const cache1 = this.cache1;
16
- if (key in cache0) {
21
+ let found = cache0.get(key);
22
+ if (found !== undefined) {
17
23
  ++this.hits;
18
- return cache0[key];
24
+ return found;
19
25
  }
20
- if (key in cache1) {
26
+ found = cache1.get(key);
27
+ if (found !== undefined) {
21
28
  ++this.hits;
22
29
  ++this.count;
23
- const r = cache1[key];
24
- cache0[key] = r;
25
- return r;
30
+ cache0.set(key, found);
31
+ return found;
26
32
  }
27
33
  ++this.misses;
28
34
  return undefined;
29
35
  }
30
36
  set(key, value) {
31
37
  if (this.count >= this.maxSize) {
38
+ const c = this.cache1;
32
39
  this.cache1 = this.cache0;
33
- this.cache0 = Object.create(null);
40
+ this.cache0 = c;
41
+ c.clear();
34
42
  this.swaps++;
35
43
  this.count = 0;
36
44
  }
37
45
  ++this.count;
38
- this.cache0[key] = value;
46
+ this.cache0.set(key, value);
39
47
  return this;
40
48
  }
41
49
  }
42
50
  export function createCache01(size) {
43
- return new Cache01(size);
51
+ return new Cache01Map(size);
44
52
  }
45
53
  export function autoCache(fn, size = CACHE_SIZE) {
46
54
  const cache = createCache01(size);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cspell-dictionary",
3
- "version": "8.11.0",
3
+ "version": "8.13.0",
4
4
  "description": "A spelling dictionary library useful for checking words and getting suggestions.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -50,14 +50,14 @@
50
50
  "node": ">=18"
51
51
  },
52
52
  "dependencies": {
53
- "@cspell/cspell-pipe": "8.11.0",
54
- "@cspell/cspell-types": "8.11.0",
55
- "cspell-trie-lib": "8.11.0",
56
- "fast-equals": "^5.0.1",
57
- "gensequence": "^7.0.0"
53
+ "@cspell/cspell-pipe": "8.13.0",
54
+ "@cspell/cspell-types": "8.13.0",
55
+ "cspell-trie-lib": "8.13.0",
56
+ "fast-equals": "^5.0.1"
58
57
  },
59
58
  "devDependencies": {
59
+ "gensequence": "^7.0.0",
60
60
  "lorem-ipsum": "^2.0.8"
61
61
  },
62
- "gitHead": "2b85b2b458b1117870a4f0aee18fb45ce991848d"
62
+ "gitHead": "2fd3fb430cc96a8a50543f57d96b288219a11923"
63
63
  }