Skip to content
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
1976ddc
fix: CSpellRPCServer and CSpellRPCClient classes
Jason3S Jan 14, 2026
be0746e
Make sure settings can be transfered.
Jason3S Jan 14, 2026
11ead68
implement worker
Jason3S Jan 14, 2026
b56fec7
get it working
Jason3S Jan 14, 2026
2a25366
fix build
Jason3S Jan 15, 2026
f09efef
Update cspellWorker.ts
Jason3S Jan 15, 2026
33f4cd0
Update cleanValidationIssue.ts
Jason3S Jan 15, 2026
8861200
refactor RPC client / server
Jason3S Jan 15, 2026
334cbc7
more tests
Jason3S Jan 15, 2026
8b83b39
more tests
Jason3S Jan 15, 2026
725bbc4
Update clientServer.test.ts
Jason3S Jan 15, 2026
cb01191
Update packages/cspell-lib/src/lib/util/clone.ts
Jason3S Jan 15, 2026
aae32d2
Update sanitizeSettings.ts
Jason3S Jan 15, 2026
316b56f
Update packages/cspell/src/worker/cspellWorker.ts
Jason3S Jan 15, 2026
9f6da5e
Create a cspell-worker package.
Jason3S Jan 15, 2026
1e085c4
Add a simple server rpc worker.
Jason3S Jan 15, 2026
e3154a9
Add tests
Jason3S Jan 15, 2026
2db4092
Update index.test.ts.snap
Jason3S Jan 16, 2026
87174ca
Update packages/cspell-lib/src/lib/spellCheckFile.ts
Jason3S Jan 16, 2026
d26f509
fix spelliing
Jason3S Jan 16, 2026
98baf8d
fix package dir
Jason3S Jan 16, 2026
7ec62ed
Make sure the object is cloned
Jason3S Jan 16, 2026
0ba2ad5
rename memorizer to memoizer
Jason3S Jan 16, 2026
0f45cc7
Update LanguageSettings.ts
Jason3S Jan 16, 2026
55bcfc1
move cspellRPC out of lib
Jason3S Jan 16, 2026
532670b
fix build
Jason3S Jan 16, 2026
8f3dd14
Apply suggestion from @Jason3S
Jason3S Jan 16, 2026
41d9785
Update cspellWorker.ts
Jason3S Jan 16, 2026
3354c2c
Update index.test.ts
Jason3S Jan 16, 2026
d76c5ae
Update vitest.config.mjs
Jason3S Jan 16, 2026
b832a5f
fix coverage
Jason3S Jan 16, 2026
e5466a6
Update index.test.ts
Jason3S Jan 16, 2026
534dfc1
Use forks when testing worker.
Jason3S Jan 16, 2026
d2ef5b2
Add RPC to the API
Jason3S Jan 16, 2026
36be43f
separate the RPC client and server
Jason3S Jan 16, 2026
450cd6f
Update packages/cspell-lib/src/cspell-rpc/server.ts
Jason3S Jan 16, 2026
47e821b
Update packages/cspell-lib/src/lib/util/memoizeLastCall.ts
Jason3S Jan 16, 2026
13dd126
Update tsdown.config.ts
Jason3S Jan 16, 2026
353b513
Add a listener to the port as soon as possible.
Jason3S Jan 16, 2026
f33ebdb
try waiting before checking the worker.
Jason3S Jan 16, 2026
1360dfd
Merge branch 'main' into dev-worker
Jason3S Jan 16, 2026
6fdc701
Update client.ts
Jason3S Jan 16, 2026
ef6bcb3
Update cspellWorker.test.ts
Jason3S Jan 16, 2026
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
1 change: 1 addition & 0 deletions cspell-dict.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ licia
linkcode
liriliri
megistos
memoizer
Comment thread
Jason3S marked this conversation as resolved.
Outdated
mkdir
monkeyc
mshick
Expand Down
1 change: 1 addition & 0 deletions cspell.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
{ "path": "packages/cspell-trie" },
{ "path": "packages/cspell-types" },
{ "path": "packages/cspell-url" },
{ "path": "packages/cspell-worker" },
{ "path": "packages/cspell" },
{ "path": "packages/dynamic-import" },
{ "path": "packages/flatpack-json" },
Expand Down
6 changes: 6 additions & 0 deletions packages/cspell-lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
"exports": {
".": {
"import": "./dist/lib/index.js"
},
"./rpc": {
"import": "./dist/rpc/index.js"
},
"./cspell-rpc": {
"import": "./dist/cspell-rpc/index.js"
}
},
"files": [
Expand Down
64 changes: 64 additions & 0 deletions packages/cspell-lib/src/cspell-rpc/cspellRPC.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { MessageChannel } from 'node:worker_threads';

import { describe, expect, test, vi } from 'vitest';

import type { MessagePortLike } from './cspellRPC.js';
import { CSpellRPCClient, CSpellRPCServer } from './cspellRPC.js';

const oc = (...params: Parameters<typeof expect.objectContaining>) => expect.objectContaining(...params);

describe('Validate Client / Server communications', () => {
test('Check creation', async () => {
const { client, server, portClient, portServer } = createClientServerPair();

expect(client).toBeDefined();
expect(server).toBeDefined();

expect(portClient.addListener).toHaveBeenCalled();
expect(portServer.addListener).toHaveBeenCalled();
});

test('spell checking a document.', async () => {
const { client } = createClientServerPair();

const api = client.getApi();
expect(api).toBeDefined();
expect(api.spellCheckDocument).toBeDefined();

const doc = { uri: import.meta.url };
const result = await api.spellCheckDocument(doc, {}, {});
expect(result).toBeDefined();
expect(result).toEqual(oc({ issues: [], errors: undefined }));

const result2 = await api.spellCheckDocument(doc, {}, {});
expect(result2).toBeDefined();
expect(result2).toEqual(oc({ issues: [], errors: undefined }));
});
});

interface ClientServerPair {
client: CSpellRPCClient;
server: CSpellRPCServer;
portClient: MessagePortLike;
portServer: MessagePortLike;
}

function createClientServerPair(): ClientServerPair {
const channel = new MessageChannel();
const portClient = channel.port1;
const portServer = channel.port2;
spyOnPort(portServer);
spyOnPort(portClient);

const server = new CSpellRPCServer(portServer);
const client = new CSpellRPCClient(portClient);

return { client, server, portClient, portServer };
}

function spyOnPort(port: MessagePortLike) {
const spyOnAddListener = vi.spyOn(port, 'addListener');
const spyOnStart = vi.spyOn(port, 'start');
const spyOnClose = vi.spyOn(port, 'close');
return { spyOnAddListener, spyOnStart, spyOnClose };
}
62 changes: 62 additions & 0 deletions packages/cspell-lib/src/cspell-rpc/cspellRPC.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { randomUUID } from 'node:crypto';

import type { MessagePortLike, RPCClientOptions, RPCProtocol, RPCServerOptions } from '../rpc/index.js';
import { RPCClient, RPCServer } from '../rpc/index.js';
import type { spellCheckDocumentRPC } from './spellCheckFile.js';

export type { MessagePortLike } from '../rpc/index.js';

export interface CSpellRPCApi {
spellCheckDocument: typeof spellCheckDocumentRPC;
}

export type CSpellRPCServerOptions = RPCServerOptions;

export class CSpellRPCServer extends RPCServer<CSpellRPCApi> {
constructor(port: MessagePortLike, options?: CSpellRPCServerOptions) {
super(port, getCSpellRPCApi(), options);
}
}

export function createCSpellRPCServer(port: MessagePortLike, options?: CSpellRPCServerOptions): CSpellRPCServer {
return new CSpellRPCServer(port, options);
}

export type CSpellRPCClientOptions = RPCClientOptions;

export class CSpellRPCClient extends RPCClient<CSpellRPCApi> {
constructor(port: MessagePortLike, options?: CSpellRPCClientOptions) {
super(port, { randomUUID, ...options });
}

getApi(): RPCProtocol<CSpellRPCApi> {
return super.getApi(Object.keys(getCSpellRPCApi()) as Array<keyof CSpellRPCApi>);
}
}

export function createCSpellRPCClient(port: MessagePortLike, options?: CSpellRPCClientOptions): CSpellRPCClient {
return new CSpellRPCClient(port, options);
}

let pSpellCheckFileJs: Promise<{ spellCheckDocumentRPC: typeof spellCheckDocumentRPC }> | undefined = undefined;

/**
* Get the CSpell RPC API.
*
* NOTE: This function lazy loads the implementation to avoid loading unnecessary during initialization of workers.
*
* @returns the api implementation.
*/
function getCSpellRPCApi(): CSpellRPCApi {
return {
spellCheckDocument: async (...params) => {
const { spellCheckDocumentRPC } = await getSpellCheckFileJs();
return spellCheckDocumentRPC(...params);
},
};

function getSpellCheckFileJs() {
pSpellCheckFileJs ??= import('./spellCheckFile.js');
return pSpellCheckFileJs;
}
}
8 changes: 8 additions & 0 deletions packages/cspell-lib/src/cspell-rpc/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export type { CSpellRPCApi } from './cspellRPC.js';
export {
createCSpellRPCClient,
createCSpellRPCServer,
CSpellRPCClient,
CSpellRPCServer,
CSpellRPCServerOptions,
} from './cspellRPC.js';
1 change: 1 addition & 0 deletions packages/cspell-lib/src/cspell-rpc/spellCheckFile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { spellCheckDocumentRPC } from '../lib/spellCheckFile.js';
6 changes: 3 additions & 3 deletions packages/cspell-lib/src/lib/Settings/LanguageSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ function stringToList(sList: string): string[] {
.filter((s) => !!s);
}

function memorizer<K, V>(resolver: (k: K) => V): (k: K) => V {
function memoize<K, V>(resolver: (k: K) => V): (k: K) => V {
const cache = createAutoResolveCache<K, V>();
return (k: K) => cache.get(k, resolver);
}

const _normalizeLanguageId = memorizer(__normalizeLanguageId);
const _normalizeLanguageId = memoize(__normalizeLanguageId);
function __normalizeLanguageId(langId: LanguageId): Set<LanguageId> {
const langIds = stringToList(langId);
return new Set<LanguageId>(langIds.map((a) => a.toLowerCase()));
Expand All @@ -50,7 +50,7 @@ export function normalizeLanguageId(langId: LanguageId | LanguageId[]): Set<Lang
return _normalizeLanguageId(typeof langId === 'string' ? langId : langId.join(','));
}

const _normalizeLocale = memorizer(__normalizeLocale);
const _normalizeLocale = memoize(__normalizeLocale);
function __normalizeLocale(locale: LocaleId): Set<LocaleId> {
const locales = localesToList(locale);
return new Set<LocaleId>(locales.map((locale) => locale.toLowerCase().replaceAll(/[^a-z]/g, '')));
Expand Down
Loading
Loading