Skip to content

Commit c22bdf9

Browse files
authored
Backport PR jupyterlab#11398: fix jupyterlab#11377 & bump Yjs dependencies & fix modeldb overwriting yjs content (jupyterlab#11408)
1 parent 4852e50 commit c22bdf9

File tree

13 files changed

+93
-37
lines changed

13 files changed

+93
-37
lines changed

dev_mode/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@
121121
"@lumino/widgets": "^1.19.0",
122122
"react": "^17.0.1",
123123
"react-dom": "^17.0.1",
124-
"yjs": "^13.5.6"
124+
"yjs": "^13.5.17"
125125
},
126126
"dependencies": {
127127
"@jupyterlab/application": "~3.2.2",
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright (c) Jupyter Development Team.
2+
// Distributed under the terms of the Modified BSD License.
3+
4+
import { test } from '@jupyterlab/galata';
5+
import { expect } from '@playwright/test';
6+
7+
const fileName = 'notebook.ipynb';
8+
const COMPLETER_SELECTOR = '.jp-Completer';
9+
10+
test.describe('Completer', () => {
11+
test.beforeEach(async ({ page }) => {
12+
await page.notebook.createNew(fileName);
13+
});
14+
15+
test('Open completer', async ({ page }) => {
16+
await page.notebook.setCell(
17+
0,
18+
'code',
19+
'option_1 = 1\n' + 'option_2 = lambda x: x\n' + 'option_3 = int'
20+
);
21+
await page.notebook.runCell(0, true);
22+
await page.notebook.addCell('code', 'option');
23+
await page.notebook.enterCellEditingMode(1);
24+
25+
// we need to wait until the completer gets bound to the cell after entering it
26+
await page.waitForTimeout(50);
27+
await page.keyboard.press('Tab');
28+
29+
const completer = page.locator(COMPLETER_SELECTOR);
30+
await completer.waitFor();
31+
32+
const imageName = 'completer.png';
33+
// TODO: on first trigger types are not properly displayed, reference image will need updating
34+
expect(await completer.screenshot()).toMatchSnapshot(imageName);
35+
});
36+
37+
test('Filter completer suggestions by typing', async ({ page }) => {
38+
// test against https://github.com/jupyterlab/jupyterlab/issues/11377
39+
40+
// `getopt` did not change much in many years, it should be stable
41+
await page.notebook.setCell(0, 'code', 'import getopt');
42+
await page.notebook.runCell(0, true);
43+
await page.notebook.addCell('code', 'getopt.');
44+
await page.notebook.enterCellEditingMode(1);
45+
46+
// we need to wait until the completer gets bound to the cell after entering it
47+
await page.waitForTimeout(50);
48+
await page.keyboard.press('Tab');
49+
50+
const completer = page.locator(COMPLETER_SELECTOR);
51+
await completer.waitFor();
52+
53+
await page.keyboard.type('g', { delay: 10 });
54+
55+
const imageName = 'completer-filter.png';
56+
expect(await completer.screenshot()).toMatchSnapshot(imageName);
57+
});
58+
});
6.99 KB
Loading
3.71 KB
Loading

jupyterlab/staging/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@
121121
"@lumino/widgets": "^1.19.0",
122122
"react": "^17.0.1",
123123
"react-dom": "^17.0.1",
124-
"yjs": "^13.5.6"
124+
"yjs": "^13.5.17"
125125
},
126126
"dependencies": {
127127
"@jupyterlab/application": "~3.2.2",

packages/cells/src/model.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
} from '@jupyterlab/observables';
2929

3030
import { IOutputAreaModel, OutputAreaModel } from '@jupyterlab/outputarea';
31+
const globalModelDBMutex = models.createMutex();
3132

3233
/**
3334
* The definition of a model object for a cell.
@@ -308,7 +309,7 @@ export class CellModel extends CodeEditor.Model implements ICellModel {
308309
event: IObservableJSON.IChangedArgs
309310
): void {
310311
const metadata = this.sharedModel.getMetadata();
311-
this._modelDBMutex(() => {
312+
globalModelDBMutex(() => {
312313
switch (event.type) {
313314
case 'add':
314315
this._changeCellMetadata(metadata, event);
@@ -377,7 +378,7 @@ export class CellModel extends CodeEditor.Model implements ICellModel {
377378
change: models.CellChange<models.ISharedBaseCellMetadata>
378379
): void {
379380
super._onSharedModelChanged(sender, change);
380-
this._modelDBMutex(() => {
381+
globalModelDBMutex(() => {
381382
if (change.metadataChange) {
382383
const newValue = change.metadataChange
383384
?.newValue as models.ISharedBaseCellMetadata;
@@ -420,11 +421,6 @@ export class CellModel extends CodeEditor.Model implements ICellModel {
420421
protected onGenericChange(): void {
421422
this.contentChanged.emit(void 0);
422423
}
423-
424-
/**
425-
* A mutex to update the shared model.
426-
*/
427-
protected readonly _modelDBMutex = models.createMutex();
428424
sharedModel: models.ISharedCell;
429425
}
430426

@@ -629,7 +625,7 @@ export class CodeCellModel extends CellModel implements ICodeCellModel {
629625

630626
executionCount.changed.connect(this._onExecutionCountChanged, this);
631627

632-
this._modelDBMutex(() => {
628+
globalModelDBMutex(() => {
633629
const sharedCell = this.sharedModel as models.ISharedCodeCell;
634630
sharedCell.setOutputs(outputs);
635631
});
@@ -790,7 +786,7 @@ export class CodeCellModel extends CellModel implements ICodeCellModel {
790786
event: IOutputAreaModel.ChangedArgs
791787
): void {
792788
const codeCell = this.sharedModel as models.YCodeCell;
793-
this._modelDBMutex(() => {
789+
globalModelDBMutex(() => {
794790
switch (event.type) {
795791
case 'add': {
796792
const outputs = event.newValues.map(output => output.toJSON());
@@ -842,7 +838,7 @@ export class CodeCellModel extends CellModel implements ICodeCellModel {
842838
change: models.CellChange<models.ISharedBaseCellMetadata>
843839
): void {
844840
super._onSharedModelChanged(sender, change);
845-
this._modelDBMutex(() => {
841+
globalModelDBMutex(() => {
846842
if (change.outputsChange) {
847843
this.clearExecution();
848844
sender.getOutputs().forEach(output => this._outputs.add(output));
@@ -864,7 +860,7 @@ export class CodeCellModel extends CellModel implements ICodeCellModel {
864860
args: ObservableValue.IChangedArgs
865861
): void {
866862
const codeCell = this.sharedModel as models.YCodeCell;
867-
this._modelDBMutex(() => {
863+
globalModelDBMutex(() => {
868864
codeCell.execution_count = args.newValue
869865
? (args.newValue as number)
870866
: null;

packages/codeeditor/src/editor.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import { JSONObject } from '@lumino/coreutils';
1717
import { IDisposable } from '@lumino/disposable';
1818
import { ISignal, Signal } from '@lumino/signaling';
1919

20+
const globalModelDBMutex = models.createMutex();
21+
2022
/**
2123
* A namespace for code editors.
2224
*
@@ -283,7 +285,7 @@ export namespace CodeEditor {
283285
sender: models.ISharedBaseCell<any>,
284286
change: models.CellChange<nbformat.IBaseCellMetadata>
285287
): void {
286-
this._mutex(() => {
288+
globalModelDBMutex(() => {
287289
if (change.sourceChange) {
288290
const value = this.modelDB.get('value') as IObservableString;
289291
let currpos = 0;
@@ -308,7 +310,7 @@ export namespace CodeEditor {
308310
value: IObservableString,
309311
event: IObservableString.IChangedArgs
310312
): void {
311-
this._mutex(() => {
313+
globalModelDBMutex(() => {
312314
this.sharedModel.transact(() => {
313315
switch (event.type) {
314316
case 'insert':
@@ -338,11 +340,6 @@ export namespace CodeEditor {
338340
*/
339341
sharedModel: models.ISharedText;
340342

341-
/**
342-
* A mutex to update the shared model.
343-
*/
344-
protected readonly _mutex = models.createMutex();
345-
346343
/**
347344
* The underlying `IModelDB` instance in which model
348345
* data is stored.

packages/codemirror/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
"@lumino/widgets": "^1.19.0",
5757
"codemirror": "~5.61.0",
5858
"react": "^17.0.1",
59-
"y-codemirror": "^2.1.1"
59+
"y-codemirror": "^3.0.0"
6060
},
6161
"devDependencies": {
6262
"@jupyterlab/testutils": "^3.2.2",

packages/codemirror/src/editor.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,13 @@ export class CodeMirrorEditor implements CodeEditor.IEditor {
164164
this.onKeydown(event);
165165
}
166166
});
167-
CodeMirror.on(editor, 'cursorActivity', () => this._onCursorActivity());
168-
if (!USE_YCODEMIRROR_BINDING) {
167+
168+
if (USE_YCODEMIRROR_BINDING) {
169+
this._yeditorBinding?.on('cursorActivity', () =>
170+
this._onCursorActivity()
171+
);
172+
} else {
173+
CodeMirror.on(editor, 'cursorActivity', () => this._onCursorActivity());
169174
CodeMirror.on(editor.getDoc(), 'beforeChange', (instance, change) => {
170175
this._beforeDocChanged(instance, change);
171176
});

packages/docprovider/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"@lumino/coreutils": "^1.5.3",
4242
"lib0": "^0.2.42",
4343
"y-websocket": "^1.3.15",
44-
"yjs": "^13.5.6"
44+
"yjs": "^13.5.17"
4545
},
4646
"devDependencies": {
4747
"@jupyterlab/testutils": "^3.2.2",

0 commit comments

Comments
 (0)