@jupyterlite/xeus 4.0.0-a0 → 4.0.0-a10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/coincident.worker.d.ts +4 -3
- package/lib/coincident.worker.js +1 -1
- package/lib/coincident.worker.js.map +1 -1
- package/lib/comlink.worker.d.ts +4 -3
- package/lib/comlink.worker.js +1 -1
- package/lib/comlink.worker.js.map +1 -1
- package/lib/index.d.ts +1 -2
- package/lib/index.js +1 -2
- package/lib/interfaces.d.ts +11 -5
- package/lib/web_worker_kernel.d.ts +7 -0
- package/lib/web_worker_kernel.js +72 -12
- package/lib/worker.base.d.ts +76 -0
- package/lib/worker.base.js +185 -0
- package/lib/worker.d.ts +23 -11
- package/lib/worker.js +163 -124
- package/package.json +8 -9
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
package/lib/interfaces.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Definitions for the Xeus kernel.
|
|
3
3
|
*/
|
|
4
|
+
import type { KernelMessage } from '@jupyterlab/services';
|
|
4
5
|
import { TDriveMethod, TDriveRequest, TDriveResponse } from '@jupyterlite/contents';
|
|
5
6
|
import { IWorkerKernel } from '@jupyterlite/kernel';
|
|
6
7
|
/**
|
|
@@ -21,15 +22,17 @@ export interface IXeusWorkerKernel extends IWorkerKernel {
|
|
|
21
22
|
* @param msg
|
|
22
23
|
*/
|
|
23
24
|
processMessage(msg: any): void;
|
|
25
|
+
/**
|
|
26
|
+
* Process stdin request, blocking until the reply is received.
|
|
27
|
+
* This is sync for the web worker, async for the UI thread.
|
|
28
|
+
* @param inputRequest
|
|
29
|
+
*/
|
|
30
|
+
processStdinRequest(inputRequest: KernelMessage.IInputRequestMsg): KernelMessage.IInputReplyMsg;
|
|
24
31
|
/**
|
|
25
32
|
* Process worker message
|
|
26
33
|
* @param msg
|
|
27
34
|
*/
|
|
28
35
|
processWorkerMessage(msg: any): void;
|
|
29
|
-
/**
|
|
30
|
-
* Register a callback for handling messages from the worker.
|
|
31
|
-
*/
|
|
32
|
-
registerCallback(callback: (msg: any) => void): void;
|
|
33
36
|
/**
|
|
34
37
|
* Whether the kernel is ready.
|
|
35
38
|
* @returns a promise that resolves when the kernel is ready.
|
|
@@ -40,8 +43,9 @@ export interface IXeusWorkerKernel extends IWorkerKernel {
|
|
|
40
43
|
* @param driveName The name of the drive
|
|
41
44
|
* @param mountpoint The mountpoint of the drive
|
|
42
45
|
* @param baseUrl The base URL of the server
|
|
46
|
+
* @param browsingContextId The current page id
|
|
43
47
|
*/
|
|
44
|
-
mount(driveName: string, mountpoint: string, baseUrl: string): Promise<void>;
|
|
48
|
+
mount(driveName: string, mountpoint: string, baseUrl: string, browsingContextId: string): Promise<void>;
|
|
45
49
|
/**
|
|
46
50
|
* Change the current working directory
|
|
47
51
|
* @param path The path to change to
|
|
@@ -62,8 +66,10 @@ export declare namespace IXeusWorkerKernel {
|
|
|
62
66
|
*/
|
|
63
67
|
interface IOptions extends IWorkerKernel.IOptions {
|
|
64
68
|
baseUrl: string;
|
|
69
|
+
kernelId: string;
|
|
65
70
|
kernelSpec: any;
|
|
66
71
|
mountDrive: boolean;
|
|
67
72
|
empackEnvMetaLink?: string;
|
|
73
|
+
browsingContextId: string;
|
|
68
74
|
}
|
|
69
75
|
}
|
|
@@ -36,12 +36,17 @@ export declare class WebWorkerKernel implements IKernel {
|
|
|
36
36
|
* Get the kernel location
|
|
37
37
|
*/
|
|
38
38
|
get location(): string;
|
|
39
|
+
/**
|
|
40
|
+
* Send kernel message to the client
|
|
41
|
+
*/
|
|
42
|
+
protected get sendMessage(): IKernel.SendMessage;
|
|
39
43
|
/**
|
|
40
44
|
* Process a message coming from the coincident web worker.
|
|
41
45
|
*
|
|
42
46
|
* @param msg The worker message to process.
|
|
43
47
|
*/
|
|
44
48
|
private _processCoincidentWorkerMessage;
|
|
49
|
+
private _assignSession;
|
|
45
50
|
/**
|
|
46
51
|
* Process a message coming from the comlink web worker.
|
|
47
52
|
*
|
|
@@ -85,6 +90,7 @@ export declare class WebWorkerKernel implements IKernel {
|
|
|
85
90
|
private _worker;
|
|
86
91
|
private _sendMessage;
|
|
87
92
|
private _executeDelegate;
|
|
93
|
+
private _inputDelegate;
|
|
88
94
|
private _parentHeader;
|
|
89
95
|
private _parent;
|
|
90
96
|
private _ready;
|
|
@@ -102,5 +108,6 @@ export declare namespace WebWorkerKernel {
|
|
|
102
108
|
mountDrive: boolean;
|
|
103
109
|
kernelSpec: any;
|
|
104
110
|
empackEnvMetaLink?: string | undefined;
|
|
111
|
+
browsingContextId: string;
|
|
105
112
|
}
|
|
106
113
|
}
|
package/lib/web_worker_kernel.js
CHANGED
|
@@ -6,6 +6,7 @@ import { wrap } from 'comlink';
|
|
|
6
6
|
import { Signal } from '@lumino/signaling';
|
|
7
7
|
import { PromiseDelegate } from '@lumino/coreutils';
|
|
8
8
|
import { PageConfig } from '@jupyterlab/coreutils';
|
|
9
|
+
import { KernelMessage } from '@jupyterlab/services';
|
|
9
10
|
import { DriveContentsProcessor } from '@jupyterlite/contents';
|
|
10
11
|
export class WebWorkerKernel {
|
|
11
12
|
/**
|
|
@@ -18,6 +19,7 @@ export class WebWorkerKernel {
|
|
|
18
19
|
this._isDisposed = false;
|
|
19
20
|
this._disposed = new Signal(this);
|
|
20
21
|
this._executeDelegate = new PromiseDelegate();
|
|
22
|
+
this._inputDelegate = new PromiseDelegate();
|
|
21
23
|
this._parentHeader = undefined;
|
|
22
24
|
this._parent = undefined;
|
|
23
25
|
this._ready = new PromiseDelegate();
|
|
@@ -74,6 +76,14 @@ export class WebWorkerKernel {
|
|
|
74
76
|
}
|
|
75
77
|
return await this._contentsProcessor.processDriveRequest(data);
|
|
76
78
|
};
|
|
79
|
+
// Stdin request is synchronous from the web worker's point of view, blocking
|
|
80
|
+
// until the reply is received. From the UI thread's point of view it is async.
|
|
81
|
+
remote.processStdinRequest = async (inputRequest) => {
|
|
82
|
+
this._processCoincidentWorkerMessage({ data: inputRequest });
|
|
83
|
+
this._inputDelegate =
|
|
84
|
+
new PromiseDelegate();
|
|
85
|
+
return await this._inputDelegate.promise;
|
|
86
|
+
};
|
|
77
87
|
}
|
|
78
88
|
else {
|
|
79
89
|
this._worker.onmessage = e => {
|
|
@@ -83,10 +93,12 @@ export class WebWorkerKernel {
|
|
|
83
93
|
}
|
|
84
94
|
remote
|
|
85
95
|
.initialize({
|
|
96
|
+
kernelId: this.id,
|
|
86
97
|
kernelSpec: this._kernelSpec,
|
|
87
98
|
baseUrl: PageConfig.getBaseUrl(),
|
|
88
99
|
mountDrive: options.mountDrive,
|
|
89
|
-
empackEnvMetaLink: this._empackEnvMetaLink
|
|
100
|
+
empackEnvMetaLink: this._empackEnvMetaLink,
|
|
101
|
+
browsingContextId: options.browsingContextId
|
|
90
102
|
})
|
|
91
103
|
.then(this._ready.resolve.bind(this._ready));
|
|
92
104
|
return remote;
|
|
@@ -97,11 +109,12 @@ export class WebWorkerKernel {
|
|
|
97
109
|
await this._sendMessageToWorker(msg);
|
|
98
110
|
}
|
|
99
111
|
async _sendMessageToWorker(msg) {
|
|
100
|
-
if (msg.header.msg_type
|
|
101
|
-
this.
|
|
112
|
+
if (msg.header.msg_type === 'input_reply') {
|
|
113
|
+
this._inputDelegate.resolve(msg);
|
|
102
114
|
}
|
|
103
|
-
|
|
104
|
-
|
|
115
|
+
else {
|
|
116
|
+
this._executeDelegate = new PromiseDelegate();
|
|
117
|
+
await this._remoteKernel.processMessage({ msg, parent: this.parent });
|
|
105
118
|
return await this._executeDelegate.promise;
|
|
106
119
|
}
|
|
107
120
|
}
|
|
@@ -123,6 +136,12 @@ export class WebWorkerKernel {
|
|
|
123
136
|
get location() {
|
|
124
137
|
return this._location;
|
|
125
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Send kernel message to the client
|
|
141
|
+
*/
|
|
142
|
+
get sendMessage() {
|
|
143
|
+
return this._sendMessage;
|
|
144
|
+
}
|
|
126
145
|
/**
|
|
127
146
|
* Process a message coming from the coincident web worker.
|
|
128
147
|
*
|
|
@@ -142,19 +161,60 @@ export class WebWorkerKernel {
|
|
|
142
161
|
this._executeDelegate.resolve();
|
|
143
162
|
}
|
|
144
163
|
}
|
|
164
|
+
_assignSession(msg) {
|
|
165
|
+
var _a, _b, _c, _d;
|
|
166
|
+
msg.header.session = (_b = (_a = this._parentHeader) === null || _a === void 0 ? void 0 : _a.session) !== null && _b !== void 0 ? _b : '';
|
|
167
|
+
msg.session = (_d = (_c = this._parentHeader) === null || _c === void 0 ? void 0 : _c.session) !== null && _d !== void 0 ? _d : '';
|
|
168
|
+
return msg;
|
|
169
|
+
}
|
|
145
170
|
/**
|
|
146
171
|
* Process a message coming from the comlink web worker.
|
|
147
172
|
*
|
|
148
173
|
* @param msg The worker message to process.
|
|
149
174
|
*/
|
|
150
175
|
_processComlinkWorkerMessage(msg) {
|
|
151
|
-
var _a, _b
|
|
176
|
+
var _a, _b;
|
|
152
177
|
if (!msg.header) {
|
|
153
|
-
|
|
178
|
+
if (msg === null || msg === void 0 ? void 0 : msg._stream) {
|
|
179
|
+
const parentHeaderValue = this._parentHeader;
|
|
180
|
+
const { name, text } = msg._stream;
|
|
181
|
+
if (name === 'stderr') {
|
|
182
|
+
const errorMessage = KernelMessage.createMessage({
|
|
183
|
+
msgType: 'execute_reply',
|
|
184
|
+
channel: 'shell',
|
|
185
|
+
parentHeader: parentHeaderValue,
|
|
186
|
+
session: (_a = parentHeaderValue === null || parentHeaderValue === void 0 ? void 0 : parentHeaderValue.session) !== null && _a !== void 0 ? _a : '',
|
|
187
|
+
content: {
|
|
188
|
+
execution_count: msg._stream.executionCount,
|
|
189
|
+
status: 'error',
|
|
190
|
+
ename: msg._stream.ename,
|
|
191
|
+
evalue: msg._stream.evalue,
|
|
192
|
+
traceback: msg._stream.traceback.join('')
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
msg = this._assignSession(errorMessage);
|
|
196
|
+
this._sendMessage(msg);
|
|
197
|
+
}
|
|
198
|
+
const message = KernelMessage.createMessage({
|
|
199
|
+
channel: 'iopub',
|
|
200
|
+
msgType: 'stream',
|
|
201
|
+
session: (_b = parentHeaderValue === null || parentHeaderValue === void 0 ? void 0 : parentHeaderValue.session) !== null && _b !== void 0 ? _b : '',
|
|
202
|
+
parentHeader: parentHeaderValue,
|
|
203
|
+
content: {
|
|
204
|
+
name,
|
|
205
|
+
text
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
msg = this._assignSession(message);
|
|
209
|
+
this._sendMessage(msg);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
this._sendMessage(this._assignSession(msg));
|
|
154
217
|
}
|
|
155
|
-
msg.header.session = (_b = (_a = this._parentHeader) === null || _a === void 0 ? void 0 : _a.session) !== null && _b !== void 0 ? _b : '';
|
|
156
|
-
msg.session = (_d = (_c = this._parentHeader) === null || _c === void 0 ? void 0 : _c.session) !== null && _d !== void 0 ? _d : '';
|
|
157
|
-
this._sendMessage(msg);
|
|
158
218
|
// resolve promise
|
|
159
219
|
if (msg.header.msg_type === 'status' &&
|
|
160
220
|
msg.content.execution_state === 'idle') {
|
|
@@ -217,12 +277,12 @@ export class WebWorkerKernel {
|
|
|
217
277
|
localPath = options.location;
|
|
218
278
|
}
|
|
219
279
|
await this._remoteKernel.ready();
|
|
220
|
-
await this._remoteKernel.mount(driveName, '/drive', PageConfig.getBaseUrl());
|
|
280
|
+
await this._remoteKernel.mount(driveName, '/drive', PageConfig.getBaseUrl(), options.browsingContextId);
|
|
221
281
|
if (await this._remoteKernel.isDir('/files')) {
|
|
222
282
|
await this._remoteKernel.cd('/files');
|
|
223
283
|
}
|
|
224
284
|
else {
|
|
225
|
-
await this._remoteKernel.cd(localPath);
|
|
285
|
+
await this._remoteKernel.cd(`/drive/${localPath}`);
|
|
226
286
|
}
|
|
227
287
|
}
|
|
228
288
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { IXeusWorkerKernel } from './interfaces';
|
|
2
|
+
import { ILogger } from '@emscripten-forge/mambajs';
|
|
3
|
+
export declare class XeusWorkerLoggerBase implements ILogger {
|
|
4
|
+
constructor(kernelId: string);
|
|
5
|
+
log(...msg: any[]): void;
|
|
6
|
+
warn(...msg: any[]): void;
|
|
7
|
+
error(...msg: any[]): void;
|
|
8
|
+
private _id;
|
|
9
|
+
private _channel;
|
|
10
|
+
executionCount: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The base class for the worker kernel
|
|
14
|
+
*
|
|
15
|
+
* Meant to be extended in order to load kernels from other sources, implement custom magics etc.
|
|
16
|
+
*/
|
|
17
|
+
export declare abstract class XeusRemoteKernelBase {
|
|
18
|
+
constructor(options?: XeusRemoteKernelBase.IOptions);
|
|
19
|
+
ready(): Promise<void>;
|
|
20
|
+
cd(path: string): Promise<void>;
|
|
21
|
+
isDir(path: string): Promise<boolean>;
|
|
22
|
+
processMessage(event: any): Promise<void>;
|
|
23
|
+
protected get Module(): any;
|
|
24
|
+
protected set Module(value: any);
|
|
25
|
+
protected get logger(): XeusWorkerLoggerBase;
|
|
26
|
+
initialize(options: IXeusWorkerKernel.IOptions): Promise<void>;
|
|
27
|
+
protected initializeLogger(options: IXeusWorkerKernel.IOptions): XeusWorkerLoggerBase;
|
|
28
|
+
/**
|
|
29
|
+
* Initialize the emscripten Module
|
|
30
|
+
* @param options
|
|
31
|
+
*/
|
|
32
|
+
protected abstract initializeModule(options: IXeusWorkerKernel.IOptions): any;
|
|
33
|
+
/**
|
|
34
|
+
* Initialize the this.Module.FS as needed
|
|
35
|
+
* @param options
|
|
36
|
+
*/
|
|
37
|
+
protected abstract initializeFileSystem(options: IXeusWorkerKernel.IOptions): Promise<any>;
|
|
38
|
+
/**
|
|
39
|
+
* Initialize the interpreter if needed
|
|
40
|
+
* @param options
|
|
41
|
+
*/
|
|
42
|
+
protected abstract initializeInterpreter(options: IXeusWorkerKernel.IOptions): Promise<any>;
|
|
43
|
+
/**
|
|
44
|
+
* Add get_stdin function to globalThis that takes an input_request message, blocks
|
|
45
|
+
* until the corresponding input_reply is received and returns the input_reply message.
|
|
46
|
+
* If an error occurs return an object of the form { error: "Error explanation" }
|
|
47
|
+
* This function is called by xeus-lite's get_stdin.
|
|
48
|
+
*/
|
|
49
|
+
protected abstract initializeStdin(baseUrl: string, browsingContextId: string): void;
|
|
50
|
+
/**
|
|
51
|
+
* Setup custom Emscripten FileSystem
|
|
52
|
+
*/
|
|
53
|
+
abstract mount(driveName: string, mountpoint: string, baseUrl: string, browsingContextId: string): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Implements dynamic installation of packages
|
|
56
|
+
*/
|
|
57
|
+
protected abstract install(channels: string[], specs: string[], pipSpecs: string[]): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Implements dynamic installation of packages
|
|
60
|
+
*/
|
|
61
|
+
protected abstract listInstalledPackages(): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Process magics prior to executing code
|
|
64
|
+
* @returns the runnable code without magics
|
|
65
|
+
*/
|
|
66
|
+
protected processMagics(code: string): Promise<string>;
|
|
67
|
+
protected xkernel: any;
|
|
68
|
+
protected xserver: any;
|
|
69
|
+
protected setKernelReady: (value: void) => void;
|
|
70
|
+
private _ready;
|
|
71
|
+
private _logger;
|
|
72
|
+
}
|
|
73
|
+
export declare namespace XeusRemoteKernelBase {
|
|
74
|
+
interface IOptions {
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// Copyright (c) Thorsten Beier
|
|
2
|
+
// Copyright (c) JupyterLite Contributors
|
|
3
|
+
// Distributed under the terms of the Modified BSD License.
|
|
4
|
+
import { waitRunDependencies, parse } from '@emscripten-forge/mambajs';
|
|
5
|
+
const STREAM = { log: 'stdout', warn: 'stdout', error: 'stderr' };
|
|
6
|
+
export class XeusWorkerLoggerBase {
|
|
7
|
+
constructor(kernelId) {
|
|
8
|
+
this.executionCount = 0;
|
|
9
|
+
this._id = kernelId;
|
|
10
|
+
this._channel = new BroadcastChannel('/xeus-kernel-logs-broadcast');
|
|
11
|
+
}
|
|
12
|
+
log(...msg) {
|
|
13
|
+
postMessage({
|
|
14
|
+
_stream: {
|
|
15
|
+
name: STREAM['log'],
|
|
16
|
+
text: msg.join(' ') + '\n'
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
this._channel.postMessage({
|
|
20
|
+
kernelId: this._id,
|
|
21
|
+
payload: { type: 'text', level: 'info', data: msg.join(' ') }
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
warn(...msg) {
|
|
25
|
+
postMessage({
|
|
26
|
+
_stream: {
|
|
27
|
+
name: STREAM['warn'],
|
|
28
|
+
text: msg.join(' ') + '\n'
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
this._channel.postMessage({
|
|
32
|
+
kernelId: this._id,
|
|
33
|
+
payload: { type: 'text', level: 'warning', data: msg.join(' ') }
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
error(...msg) {
|
|
37
|
+
postMessage({
|
|
38
|
+
_stream: {
|
|
39
|
+
name: STREAM['error'],
|
|
40
|
+
evalue: msg.join(''),
|
|
41
|
+
traceback: [],
|
|
42
|
+
executionCount: this.executionCount,
|
|
43
|
+
text: msg.join('')
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
this._channel.postMessage({
|
|
47
|
+
kernelId: this._id,
|
|
48
|
+
payload: { type: 'text', level: 'critical', data: msg.join(' ') }
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The base class for the worker kernel
|
|
54
|
+
*
|
|
55
|
+
* Meant to be extended in order to load kernels from other sources, implement custom magics etc.
|
|
56
|
+
*/
|
|
57
|
+
export class XeusRemoteKernelBase {
|
|
58
|
+
constructor(options = {}) {
|
|
59
|
+
this._ready = new Promise(resolve => {
|
|
60
|
+
this.setKernelReady = resolve;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
async ready() {
|
|
64
|
+
return await this._ready;
|
|
65
|
+
}
|
|
66
|
+
async cd(path) {
|
|
67
|
+
if (!path || !this.Module.FS) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
this.Module.FS.chdir(path);
|
|
71
|
+
}
|
|
72
|
+
async isDir(path) {
|
|
73
|
+
try {
|
|
74
|
+
const lookup = this.Module.FS.lookupPath(path);
|
|
75
|
+
return this.Module.FS.isDir(lookup.node.mode);
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async processMessage(event) {
|
|
82
|
+
const msg_type = event.msg.header.msg_type;
|
|
83
|
+
await globalThis.ready;
|
|
84
|
+
if (globalThis.toplevel_promise !== null &&
|
|
85
|
+
globalThis.toplevel_promise_py_proxy !== null) {
|
|
86
|
+
await globalThis.toplevel_promise;
|
|
87
|
+
globalThis.toplevel_promise_py_proxy.delete();
|
|
88
|
+
globalThis.toplevel_promise_py_proxy = null;
|
|
89
|
+
globalThis.toplevel_promise = null;
|
|
90
|
+
}
|
|
91
|
+
if (msg_type === 'input_reply') {
|
|
92
|
+
// Should never be called as input_reply messages are handled by get_stdin
|
|
93
|
+
// via SharedArrayBuffer or service worker.
|
|
94
|
+
}
|
|
95
|
+
else if (msg_type === 'execute_request') {
|
|
96
|
+
this._logger.executionCount += 1;
|
|
97
|
+
event.msg.content.code = await this.processMagics(event.msg.content.code);
|
|
98
|
+
this.xserver.notify_listener(event.msg);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
this.xserver.notify_listener(event.msg);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
get Module() {
|
|
105
|
+
return globalThis.Module;
|
|
106
|
+
}
|
|
107
|
+
set Module(value) {
|
|
108
|
+
globalThis.Module = value;
|
|
109
|
+
}
|
|
110
|
+
get logger() {
|
|
111
|
+
return this._logger;
|
|
112
|
+
}
|
|
113
|
+
async initialize(options) {
|
|
114
|
+
const { baseUrl, browsingContextId, kernelSpec } = options;
|
|
115
|
+
this._logger = this.initializeLogger(options);
|
|
116
|
+
// when a toplevel cell uses an await, the cell is implicitly
|
|
117
|
+
// wrapped in a async function. Since the webloop - eventloop
|
|
118
|
+
// implementation does not support `eventloop.run_until_complete(f)`
|
|
119
|
+
// we need to convert the toplevel future in a javascript Promise
|
|
120
|
+
// this `toplevel` promise is then awaited before we
|
|
121
|
+
// execute the next cell. After the promise is awaited we need
|
|
122
|
+
// to do some cleanup and delete the python proxy
|
|
123
|
+
// (ie a js-wrapped python object) to avoid memory leaks
|
|
124
|
+
globalThis.toplevel_promise = null;
|
|
125
|
+
globalThis.toplevel_promise_py_proxy = null;
|
|
126
|
+
this.Module = await this.initializeModule(options);
|
|
127
|
+
this.Module = await createXeusModule(this.Module);
|
|
128
|
+
try {
|
|
129
|
+
await waitRunDependencies(this.Module);
|
|
130
|
+
await this.initializeFileSystem(options);
|
|
131
|
+
await this.initializeInterpreter(options);
|
|
132
|
+
this.initializeStdin(baseUrl, browsingContextId);
|
|
133
|
+
try {
|
|
134
|
+
this.xkernel = new this.Module.xkernel(kernelSpec.argv);
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
this.xkernel = new this.Module.xkernel();
|
|
138
|
+
}
|
|
139
|
+
this.xserver = this.xkernel.get_server();
|
|
140
|
+
if (!this.xserver) {
|
|
141
|
+
this._logger.error('Failed to start kernel!');
|
|
142
|
+
}
|
|
143
|
+
this.xkernel.start();
|
|
144
|
+
}
|
|
145
|
+
catch (e) {
|
|
146
|
+
if (typeof e === 'number') {
|
|
147
|
+
const msg = this.Module.get_exception_message(e);
|
|
148
|
+
this._logger.error(msg);
|
|
149
|
+
throw new Error(msg);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
this._logger.error(e);
|
|
153
|
+
throw e;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
this._logger.log('Kernel successfuly started!');
|
|
157
|
+
this.setKernelReady();
|
|
158
|
+
}
|
|
159
|
+
initializeLogger(options) {
|
|
160
|
+
return new XeusWorkerLoggerBase(options.kernelId);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Process magics prior to executing code
|
|
164
|
+
* @returns the runnable code without magics
|
|
165
|
+
*/
|
|
166
|
+
async processMagics(code) {
|
|
167
|
+
const { commands, run } = parse(code);
|
|
168
|
+
for (const command of commands) {
|
|
169
|
+
switch (command.type) {
|
|
170
|
+
case 'install':
|
|
171
|
+
if (command.data) {
|
|
172
|
+
const { channels, specs, pipSpecs } = command.data;
|
|
173
|
+
await this.install(channels, specs, pipSpecs);
|
|
174
|
+
}
|
|
175
|
+
break;
|
|
176
|
+
case 'list':
|
|
177
|
+
await this.listInstalledPackages();
|
|
178
|
+
break;
|
|
179
|
+
default:
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return run;
|
|
184
|
+
}
|
|
185
|
+
}
|
package/lib/worker.d.ts
CHANGED
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
import { IXeusWorkerKernel } from './interfaces';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
import { XeusRemoteKernelBase } from './worker.base';
|
|
3
|
+
/**
|
|
4
|
+
* A worker kernel that is backed by an empack environment
|
|
5
|
+
*/
|
|
6
|
+
export declare abstract class EmpackedXeusRemoteKernel extends XeusRemoteKernelBase {
|
|
7
|
+
protected initializeModule(options: IXeusWorkerKernel.IOptions): Promise<any>;
|
|
8
|
+
protected initializeFileSystem(options: IXeusWorkerKernel.IOptions): Promise<any>;
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
* @param
|
|
10
|
+
* Initialize the interpreter if needed
|
|
11
|
+
* @param options
|
|
12
12
|
*/
|
|
13
|
-
|
|
14
|
-
protected
|
|
13
|
+
protected initializeInterpreter(options: IXeusWorkerKernel.IOptions): Promise<void>;
|
|
14
|
+
protected install(channels: string[], specs: string[], pipSpecs: string[]): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Implements dynamic installation of packages
|
|
17
|
+
*/
|
|
18
|
+
protected listInstalledPackages(): Promise<void>;
|
|
19
|
+
private _reloadPackagesInFS;
|
|
20
|
+
private _pythonVersion;
|
|
21
|
+
private _prefix;
|
|
22
|
+
private _pkgRootUrl;
|
|
23
|
+
private _sharedLibs;
|
|
24
|
+
private _installedPackages;
|
|
25
|
+
private _paths;
|
|
26
|
+
private _untarjs;
|
|
15
27
|
}
|
|
16
28
|
export declare namespace XeusRemoteKernel {
|
|
17
29
|
interface IOptions {
|