Skip to content
This repository has been archived by the owner on Mar 22, 2024. It is now read-only.

Commit

Permalink
Allow to init and start separately. Enforce dipose before start
Browse files Browse the repository at this point in the history
  • Loading branch information
kaisalmen committed Nov 8, 2023
1 parent 6481122 commit d71c97e
Show file tree
Hide file tree
Showing 12 changed files with 149 additions and 79 deletions.
14 changes: 7 additions & 7 deletions package-lock.json

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

6 changes: 3 additions & 3 deletions packages/examples/package.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
{
"name": "monaco-editor-wrapper-examples",
"private": true,
"version": "3.4.0-next.0",
"version": "3.4.0-next.2",
"type": "module",
"dependencies": {
"@codingame/monaco-vscode-configuration-service-override": "~1.83.5",
"@codingame/monaco-vscode-editor-service-override": "~1.83.5",
"@codingame/monaco-vscode-json-default-extension": "~1.83.5",
"@codingame/monaco-vscode-keybindings-service-override": "~1.83.5",
"@codingame/monaco-vscode-python-default-extension": "~1.83.5",
"@typefox/monaco-editor-react": "~2.4.0-next.0",
"@typefox/monaco-editor-react": "~2.4.0-next.2",
"http-server": "~14.1.1",
"langium": "~2.1.1",
"langium-statemachine-dsl": "~2.1.0",
"monaco-editor": "npm:@codingame/monaco-editor-treemended@>=1.83.5 <1.84.0",
"monaco-editor-workers": "~0.44.0",
"monaco-editor-wrapper": "~3.4.0-next.0",
"monaco-editor-wrapper": "~3.4.0-next.2",
"monaco-languageclient": "~7.0.0",
"monaco-languageclient-examples": "~7.0.0",
"react": "~18.2.0",
Expand Down
1 change: 1 addition & 0 deletions packages/examples/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const disposeEditor = async (useDiffEditor: boolean) => {
};

const restartEditor = async (userConfig: UserConfig, htmlElement: HTMLElement | null) => {
await wrapper.dispose();
await wrapper.start(userConfig, htmlElement);
logEditorInfo(userConfig);
};
Expand Down
17 changes: 13 additions & 4 deletions packages/examples/src/langium/wrapperLangium.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { buildWorkerDefinition } from 'monaco-editor-workers';
buildWorkerDefinition('../../../node_modules/monaco-editor-workers/dist/workers/', new URL('', window.location.href).href, false);

let wrapper: MonacoEditorLanguageClientWrapper | undefined;
let extended = false;

const htmlElement = document.getElementById('monaco-editor-root');
export const run = async () => {
Expand All @@ -26,7 +27,9 @@ export const run = async () => {
export const startLangiumClientExtended = async () => {
try {
if (checkStarted()) return;
disableButton('button-start-classic');
extended = true;
disableButton('button-start-classic', true);
disableButton('button-start-extended', true);
const config = await setupLangiumClientExtended();
wrapper = new MonacoEditorLanguageClientWrapper();
wrapper.start(config, htmlElement);
Expand All @@ -38,7 +41,8 @@ export const startLangiumClientExtended = async () => {
export const startLangiumClientClassic = async () => {
try {
if (checkStarted()) return;
disableButton('button-start-extended');
disableButton('button-start-classic', true);
disableButton('button-start-extended', true);
const config = await setupLangiumClientClassic();
wrapper = new MonacoEditorLanguageClientWrapper();
await wrapper.start(config, htmlElement!);
Expand All @@ -55,10 +59,10 @@ const checkStarted = () => {
return false;
};

const disableButton = (id: string) => {
const disableButton = (id: string, disabled: boolean) => {
const button = document.getElementById(id) as HTMLButtonElement;
if (button !== null) {
button.disabled = true;
button.disabled = disabled;
}
};

Expand All @@ -67,6 +71,11 @@ export const disposeEditor = async () => {
wrapper.reportStatus();
await wrapper.dispose();
wrapper = undefined;
if (extended) {
disableButton('button-start-extended', false);
} else {
disableButton('button-start-classic', false);
}
};

export const loadLangiumWorker = () => {
Expand Down
5 changes: 4 additions & 1 deletion packages/examples/src/wrapperAdvanced.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import getKeybindingsServiceOverride from '@codingame/monaco-vscode-keybindings-service-override';
import 'monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution.js';
import 'monaco-editor/esm/vs/language/typescript/monaco.contribution.js';
import { EditorAppConfigClassic, LanguageClientError, MonacoEditorLanguageClientWrapper, UserConfig } from 'monaco-editor-wrapper';
import { buildWorkerDefinition } from 'monaco-editor-workers';

Expand Down Expand Up @@ -114,6 +115,7 @@ const sleepOne = (milliseconds: number) => {
setTimeout(async () => {
alert(`Updating editors after ${milliseconds}ms`);

await wrapper42.dispose();
wrapper42Config.languageClientConfig = undefined;
const appConfig42 = wrapper42Config.wrapperConfig.editorAppConfig as EditorAppConfigClassic;
appConfig42.languageId = 'javascript';
Expand All @@ -129,6 +131,7 @@ const sleepOne = (milliseconds: number) => {
codeOriginal: 'text 1234'
});

await wrapper44.dispose();
const appConfig44 = wrapper44Config.wrapperConfig.editorAppConfig as EditorAppConfigClassic;
appConfig44.languageId = 'text/plain';
appConfig44.useDiffEditor = true;
Expand All @@ -152,10 +155,10 @@ const sleepTwo = (milliseconds: number) => {
setTimeout(async () => {
alert(`Updating last editor after ${milliseconds}ms`);

await wrapper44.dispose();
const appConfig44 = wrapper44Config.wrapperConfig.editorAppConfig as EditorAppConfigClassic;
appConfig44.useDiffEditor = false;
appConfig44.theme = 'vs-dark';

await wrapper44.start(wrapper44Config, document.getElementById('monaco-editor-root-44'));
console.log('Restarted wrapper44.');
}, milliseconds);
Expand Down
6 changes: 3 additions & 3 deletions packages/monaco-editor-react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@typefox/monaco-editor-react",
"version": "2.4.0-next.0",
"version": "2.4.0-next.2",
"license": "MIT",
"description": "React component for Monaco-Editor and Monaco Languageclient",
"keywords": [
Expand Down Expand Up @@ -51,12 +51,12 @@
},
"dependencies": {
"monaco-editor": "npm:@codingame/monaco-editor-treemended@>=1.83.5 <1.84.0",
"monaco-editor-wrapper": "~3.4.0-next.0",
"monaco-editor-wrapper": "~3.4.0-next.2",
"react": "~18.2.0",
"vscode": "npm:@codingame/monaco-vscode-api@>=1.83.5 <1.84.0"
},
"peerDependencies": {
"monaco-editor-wrapper": "~3.4.0-next.0"
"monaco-editor-wrapper": "~3.4.0-next.2"
},
"devDependencies": {
"@types/react": "~18.2.37"
Expand Down
82 changes: 52 additions & 30 deletions packages/monaco-editor-react/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export class MonacoEditorReactComp<T extends MonacoEditorProps = MonacoEditorPro
private wrapper: MonacoEditorLanguageClientWrapper = new MonacoEditorLanguageClientWrapper();
private containerElement?: HTMLDivElement;
private _subscription: IDisposable | null = null;
private isStarting?: Promise<void>;
private isRestaring?: Promise<void>;
private started: (value: void | PromiseLike<void>) => void;

constructor(props: T) {
super(props);
Expand All @@ -27,9 +28,10 @@ export class MonacoEditorReactComp<T extends MonacoEditorProps = MonacoEditorPro
await this.handleReinit();
}

private async handleReinit() {
protected async handleReinit() {
await this.destroyMonaco();
await this.initMonaco();
await this.startMonaco();
}

override async componentDidUpdate(prevProps: T) {
Expand Down Expand Up @@ -85,58 +87,78 @@ export class MonacoEditorReactComp<T extends MonacoEditorProps = MonacoEditorPro
this.destroyMonaco();
}

private assignRef = (component: HTMLDivElement) => {
protected assignRef = (component: HTMLDivElement) => {
this.containerElement = component;
};

private async destroyMonaco(): Promise<void> {
protected async destroyMonaco(): Promise<void> {
if (this.wrapper) {
await this.isStarting;
if (this.isRestaring) {
await this.isRestaring;
}
try {
await this.wrapper.dispose();
} catch {
// This is fine
// Sometimes the language client throws an error during disposal
// This should not prevent us from continue working
// The language client may throw an error during disposal.
// This should not prevent us from continue working.
}
}
if (this._subscription) {
this._subscription.dispose();
}
}

private async initMonaco() {
protected async initMonaco() {
const {
userConfig
} = this.props;

// block "destroyMonaco" until start is complete
this.isRestaring = new Promise<void>((resolve) => {
this.started = resolve;
});
await this.wrapper.init(userConfig);
}

protected async startMonaco() {
const {
className,
userConfig,
onTextChanged,
onLoad,
} = this.props;

if (this.containerElement) {
this.containerElement.className = className ?? '';

this.isStarting = this.wrapper.start(userConfig, this.containerElement);
await this.isStarting;
await this.wrapper.startNoInit(this.containerElement);
this.started();
this.isRestaring = undefined;

// once awaiting isStarting is done onLoad is called if available
onLoad && onLoad();

if (onTextChanged) {
const model = this.wrapper.getModel();
if (model) {
const verifyModelContent = () => {
const modelText = model.getValue();
onTextChanged(modelText, modelText !== userConfig.wrapperConfig.editorAppConfig.code);
};

this._subscription = model.onDidChangeContent(() => {
verifyModelContent();
});
// do it initially
verifyModelContent();
}
}
onLoad?.();

this.handleOnTextChanged();
}
}

private handleOnTextChanged() {
const {
userConfig,
onTextChanged
} = this.props;
if (!onTextChanged) return;

const model = this.wrapper.getModel();
if (model) {
const verifyModelContent = () => {
const modelText = model.getValue();
onTextChanged(modelText, modelText !== userConfig.wrapperConfig.editorAppConfig.code);
};

this._subscription = model.onDidChangeContent(() => {
verifyModelContent();
});
// do it initially
verifyModelContent();
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/monaco-editor-wrapper/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "monaco-editor-wrapper",
"version": "3.4.0-next.0",
"version": "3.4.0-next.2",
"license": "MIT",
"description": "Monaco-Editor and Monaco Languageclient Wrapper",
"keywords": [
Expand Down
11 changes: 4 additions & 7 deletions packages/monaco-editor-wrapper/src/languageClientWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ export class LanguageClientWrapper {
private languageClientConfig?: LanguageClientConfig;
private worker: Worker | undefined;
private languageId: string;
private name;
private name?: string;
private logger: Logger | undefined;

constructor(languageId: string, languageClientConfig?: LanguageClientConfig, logger?: Logger) {
init(languageId: string, languageClientConfig?: LanguageClientConfig, logger?: Logger) {
this.languageId = languageId;
if (languageClientConfig) {
this.languageClientConfig = languageClientConfig;
Expand Down Expand Up @@ -292,11 +292,8 @@ export class LanguageClientWrapper {
}
}
else {
const languageClientError: LanguageClientError = {
message: `languageClientWrapper (${this.name}): Unable to dispose monaco-languageclient: It is not yet started.`,
error: 'No error was provided.'
};
return Promise.reject(languageClientError);
// disposing the languageclient if it does not exist is considered ok
return Promise.resolve();
}
}

Expand Down
Loading

0 comments on commit d71c97e

Please sign in to comment.