Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/ipynb/src/notebookSerializer.node.ts
3292 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as vscode from 'vscode';
7
import { DeferredPromise, generateUuid } from './helper';
8
import { NotebookSerializerBase } from './notebookSerializer';
9
10
export class NotebookSerializer extends NotebookSerializerBase {
11
private experimentalSave = vscode.workspace.getConfiguration('ipynb').get('experimental.serialization', true);
12
private worker?: import('node:worker_threads').Worker;
13
private tasks = new Map<string, DeferredPromise<Uint8Array>>();
14
15
constructor(context: vscode.ExtensionContext) {
16
super(context);
17
context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(e => {
18
if (e.affectsConfiguration('ipynb.experimental.serialization')) {
19
this.experimentalSave = vscode.workspace.getConfiguration('ipynb').get('experimental.serialization', true);
20
}
21
}));
22
}
23
24
override dispose() {
25
try {
26
void this.worker?.terminate();
27
} catch {
28
//
29
}
30
super.dispose();
31
}
32
33
public override async serializeNotebook(data: vscode.NotebookData, token: vscode.CancellationToken): Promise<Uint8Array> {
34
if (this.disposed) {
35
return new Uint8Array(0);
36
}
37
38
if (this.experimentalSave) {
39
return this.serializeViaWorker(data);
40
}
41
42
return super.serializeNotebook(data, token);
43
}
44
45
private async startWorker() {
46
if (this.disposed) {
47
throw new Error('Serializer disposed');
48
}
49
if (this.worker) {
50
return this.worker;
51
}
52
const { Worker } = await import('node:worker_threads');
53
const outputDir = getOutputDir(this.context);
54
this.worker = new Worker(vscode.Uri.joinPath(this.context.extensionUri, outputDir, 'notebookSerializerWorker.js').fsPath, {});
55
this.worker.on('exit', (exitCode) => {
56
if (!this.disposed) {
57
console.error(`IPynb Notebook Serializer Worker exited unexpectedly`, exitCode);
58
}
59
this.worker = undefined;
60
});
61
this.worker.on('message', (result: { data: Uint8Array; id: string }) => {
62
const task = this.tasks.get(result.id);
63
if (task) {
64
task.complete(result.data);
65
this.tasks.delete(result.id);
66
}
67
});
68
this.worker.on('error', (err) => {
69
if (!this.disposed) {
70
console.error(`IPynb Notebook Serializer Worker errored unexpectedly`, err);
71
}
72
});
73
return this.worker;
74
}
75
private async serializeViaWorker(data: vscode.NotebookData): Promise<Uint8Array> {
76
const worker = await this.startWorker();
77
const id = generateUuid();
78
79
const deferred = new DeferredPromise<Uint8Array>();
80
this.tasks.set(id, deferred);
81
worker.postMessage({ data, id });
82
83
return deferred.p;
84
}
85
}
86
87
88
function getOutputDir(context: vscode.ExtensionContext): string {
89
const main = context.extension.packageJSON.main as string;
90
return main.indexOf('/dist/') !== -1 ? 'dist' : 'out';
91
}
92
93