Skip to content

Commit

Permalink
Fix worker call IDs with multiple worker instances (#3481)
Browse files Browse the repository at this point in the history
  • Loading branch information
mogzol authored Aug 14, 2024
1 parent 1a743b7 commit ba90037
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 37 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ All notable changes to the "prettier-vscode" extension will be documented in thi

## [Unreleased]

- Fix issue where formatting multiple files in a workspace with multiple instances of Prettier could result in files being overwritten with the contents of other files (#3423, #3040)

## [10.5.0]

- Extend list of Prettier config files by ECMAScript module extentions
Expand Down
49 changes: 23 additions & 26 deletions src/PrettierWorkerInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,63 +14,60 @@ import {
PrettierSupportLanguage,
} from "./types";

let currentCallId = 0;

const worker = new Worker(
url.pathToFileURL(path.join(__dirname, "/worker/prettier-instance-worker.js"))
);

export const PrettierWorkerInstance: PrettierInstanceConstructor = class PrettierWorkerInstance
implements PrettierInstance
{
private importResolver: {
resolve: (version: string) => void;
reject: (version: string) => void;
} | null = null;

private callMethodResolvers: Map<
private messageResolvers: Map<
number,
{
resolve: (value: unknown) => void;
reject: (value: unknown) => void;
}
> = new Map();

private currentCallMethodId = 0;

public version: string | null = null;

constructor(private modulePath: string) {
worker.on("message", ({ type, payload }) => {
switch (type) {
case "import": {
this.importResolver?.resolve(payload.version);
this.version = payload.version;
break;
}
case "callMethod": {
const resolver = this.callMethodResolvers.get(payload.id);
this.callMethodResolvers.delete(payload.id);
if (resolver) {
worker.on("message", ({ type, id, payload }) => {
const resolver = this.messageResolvers.get(id);
if (resolver) {
this.messageResolvers.delete(id);
switch (type) {
case "import": {
resolver.resolve(payload.version);
this.version = payload.version;
break;
}
case "callMethod": {
if (payload.isError) {
resolver.reject(payload.result);
} else {
resolver.resolve(payload.result);
}
break;
}
break;
}
}
});
}

public async import(): Promise</* version of imported prettier */ string> {
const promise = new Promise<string>((resolve, reject) => {
this.importResolver = { resolve, reject };
const callId = currentCallId++;
const promise = new Promise((resolve, reject) => {
this.messageResolvers.set(callId, { resolve, reject });
});
worker.postMessage({
type: "import",
id: callId,
payload: { modulePath: this.modulePath },
});
return promise;
return promise as Promise<string>;
}

public async format(
Expand Down Expand Up @@ -124,14 +121,14 @@ export const PrettierWorkerInstance: PrettierInstanceConstructor = class Prettie

// eslint-disable-next-line @typescript-eslint/no-explicit-any
private callMethod(methodName: string, methodArgs: unknown[]): Promise<any> {
const callMethodId = this.currentCallMethodId++;
const callId = currentCallId++;
const promise = new Promise((resolve, reject) => {
this.callMethodResolvers.set(callMethodId, { resolve, reject });
this.messageResolvers.set(callId, { resolve, reject });
});
worker.postMessage({
type: "callMethod",
id: callId,
payload: {
id: callMethodId,
modulePath: this.modulePath,
methodName,
methodArgs,
Expand Down
26 changes: 15 additions & 11 deletions src/worker/prettier-instance-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,40 @@ function requireInstance(modulePath) {
return prettierInstance;
}

parentPort.on("message", ({ type, payload }) => {
parentPort.on("message", ({ type, id, payload }) => {
switch (type) {
case "import": {
const { modulePath } = payload;
try {
const prettierInstance = requireInstance(modulePath);
parentPort.postMessage({
type,
id,
payload: { version: prettierInstance.version },
});
} catch {
parentPort.postMessage({
type,
id,
payload: { version: null },
});
}
break;
}
case "callMethod": {
const { modulePath, methodName, methodArgs, id } = payload;
const { modulePath, methodName, methodArgs } = payload;
const postError = (error) => {
parentPort.postMessage({
type,
payload: { result: error, id, isError: true },
id,
payload: { result: error, isError: true },
});
};
const postResult = (result) => {
parentPort.postMessage({
type,
id,
payload: { result, isError: false },
});
};
let prettierInstance = path2ModuleCache.get(modulePath);
Expand All @@ -62,10 +72,7 @@ parentPort.on("message", ({ type, payload }) => {
if (methodName === "getSupportInfo") {
value = { languages: value.languages };
}
parentPort.postMessage({
type,
payload: { result: value, id, isError: false },
});
postResult(value);
} catch (error) {
postError(error);
}
Expand All @@ -81,10 +88,7 @@ parentPort.on("message", ({ type, payload }) => {
if (methodName === "getSupportInfo") {
result = { languages: result.languages };
}
parentPort.postMessage({
type,
payload: { result, id, isError: false },
});
postResult(result);
} catch (error) {
postError(error);
}
Expand Down

0 comments on commit ba90037

Please sign in to comment.