@tlockney/cdp-kernel 0.7.2 → 0.9.0
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/README.md +4 -2
- package/dist/browser/kernel.js +211 -42
- package/dist/browser/kernel.js.map +2 -2
- package/dist/browser/target.d.ts +2 -1
- package/dist/browser/target.js +29 -7
- package/dist/browser/worker.js +47 -4
- package/dist/browser/worker.js.map +2 -2
- package/dist/bun-target.d.ts +5 -1
- package/dist/bun-target.js +32 -7
- package/dist/crash-reports.d.ts +47 -0
- package/dist/crash-reports.js +155 -0
- package/dist/globals.d.ts +35 -4
- package/dist/kernel-core.d.ts +7 -0
- package/dist/kernel-core.js +215 -35
- package/dist/kernel.js +10 -0
- package/dist/main.js +31 -14
- package/dist/message.d.ts +1 -1
- package/dist/message.js +1 -1
- package/dist/package.d.ts +2 -2
- package/dist/package.js +2 -2
- package/dist/target-api.d.ts +11 -0
- package/dist/target.d.ts +9 -2
- package/dist/target.js +66 -12
- package/dist/transform.d.ts +10 -1
- package/dist/transform.js +23 -3
- package/dist/usage.d.ts +25 -0
- package/dist/usage.js +197 -0
- package/dist/workerd-target.d.ts +13 -2
- package/dist/workerd-target.js +36 -6
- package/dist/workers-project.js +2 -0
- package/package.json +1 -1
- package/runtime/bootstrap.mjs +65 -7
- package/runtime/browser-worker.mjs +6 -2
- package/runtime/comm.d.mts +87 -1
- package/runtime/display.d.mts +261 -4
- package/runtime/display.mjs +42 -1
- package/runtime/evaluator.d.mts +5 -1
- package/runtime/evaluator.mjs +12 -1
- package/runtime/widget.d.mts +205 -6
- package/runtime/workerd-worker.mjs +6 -2
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ runtime: Node or Deno over the Chrome DevTools Protocol, or Bun, workerd and
|
|
|
7
7
|
celld, which evaluate cells in-process. In principle, anything else whose
|
|
8
8
|
inspector speaks CDP works too. The kernel can also run inside a web page,
|
|
9
9
|
with cells in a Web Worker and no server
|
|
10
|
-
([The browser](https://cdp-kernel.org/docs/integration-browser)
|
|
10
|
+
([The browser](https://cdp-kernel.org/docs/integration-browser)).
|
|
11
11
|
|
|
12
12
|
**Website:** <https://cdp-kernel.org/> ·
|
|
13
13
|
**Docs:** [cdp-kernel.org/docs](https://cdp-kernel.org/docs/)
|
|
@@ -87,7 +87,9 @@ New to Jupyter? Start with
|
|
|
87
87
|
[Choosing a runtime](https://cdp-kernel.org/docs/runtimes),
|
|
88
88
|
[Widgets and comms](https://cdp-kernel.org/docs/widgets),
|
|
89
89
|
[Debugger](https://cdp-kernel.org/docs/debugger)
|
|
90
|
-
- Reference: [
|
|
90
|
+
- Reference: [`jupyter` reference](https://cdp-kernel.org/docs/jupyter-reference),
|
|
91
|
+
[Widgets and comms reference](https://cdp-kernel.org/docs/widgets-reference),
|
|
92
|
+
[Editor types](https://cdp-kernel.org/docs/editor-types),
|
|
91
93
|
[Known gaps](https://cdp-kernel.org/docs/known-gaps),
|
|
92
94
|
[Support policy](https://cdp-kernel.org/docs/support)
|
|
93
95
|
- Internals: [Architecture](https://cdp-kernel.org/docs/architecture),
|
package/dist/browser/kernel.js
CHANGED
|
@@ -28199,7 +28199,7 @@ function rewriteImport(code, node, index) {
|
|
|
28199
28199
|
if (spec.type === "ImportNamespaceSpecifier") return `${local} = ${ns}`;
|
|
28200
28200
|
return `${local} = ${ns}[${JSON.stringify(importedName(spec))}]`;
|
|
28201
28201
|
});
|
|
28202
|
-
return `var ${ns} = ${load};
|
|
28202
|
+
return `var ${ns} = ${load}; let ${bindings.join(", ")};`;
|
|
28203
28203
|
}
|
|
28204
28204
|
function parseCell(js) {
|
|
28205
28205
|
try {
|
|
@@ -28216,6 +28216,12 @@ function parseCell(js) {
|
|
|
28216
28216
|
function rewriteModuleSyntax(js) {
|
|
28217
28217
|
const program = parseCell(js);
|
|
28218
28218
|
const edits = [];
|
|
28219
|
+
for (const statement of program.body) {
|
|
28220
|
+
const decl = statement.type === "ExportNamedDeclaration" ? statement.declaration : statement;
|
|
28221
|
+
if (decl?.type === "VariableDeclaration" && decl.kind === "const") {
|
|
28222
|
+
edits.push({ start: decl.start, end: decl.start + "const".length, text: "let " });
|
|
28223
|
+
}
|
|
28224
|
+
}
|
|
28219
28225
|
let importIndex = 0;
|
|
28220
28226
|
full(program, (node) => {
|
|
28221
28227
|
switch (node.type) {
|
|
@@ -28376,7 +28382,7 @@ var init_transform = __esm({
|
|
|
28376
28382
|
SHIM = "__cdpk";
|
|
28377
28383
|
YIELD = `await ${SHIM}.tick();
|
|
28378
28384
|
`;
|
|
28379
|
-
PRELUDE = `'use strict'; ${YIELD}`;
|
|
28385
|
+
PRELUDE = `'use strict'; ${SHIM}.startCell(); ${YIELD}`;
|
|
28380
28386
|
SETTLE = `
|
|
28381
28387
|
;let ${SHIM}_settled = await ${SHIM}.tick();`;
|
|
28382
28388
|
CellSyntaxError = class extends Error {
|
|
@@ -28388,7 +28394,7 @@ var init_transform = __esm({
|
|
|
28388
28394
|
});
|
|
28389
28395
|
|
|
28390
28396
|
// src/message.ts
|
|
28391
|
-
var PROTOCOL_VERSION = "5.
|
|
28397
|
+
var PROTOCOL_VERSION = "5.5";
|
|
28392
28398
|
function makeHeader(session, msgType) {
|
|
28393
28399
|
return {
|
|
28394
28400
|
msg_id: crypto.randomUUID(),
|
|
@@ -28758,12 +28764,43 @@ function clip(frames) {
|
|
|
28758
28764
|
|
|
28759
28765
|
// src/kernel-core.ts
|
|
28760
28766
|
var TYPESCRIPT_VERSION = "6";
|
|
28767
|
+
var launchFailures = /* @__PURE__ */ new WeakSet();
|
|
28761
28768
|
function fromBase64(text) {
|
|
28762
28769
|
return Uint8Array.from(atob(text), (c) => c.charCodeAt(0));
|
|
28763
28770
|
}
|
|
28764
28771
|
var INTERRUPT_REPLY_WAIT_MS = 1e3;
|
|
28765
28772
|
var NO_INPUT = { value: null, interrupted: false };
|
|
28773
|
+
var ShellQueue = class {
|
|
28774
|
+
items = [];
|
|
28775
|
+
#wake = null;
|
|
28776
|
+
#closed = false;
|
|
28777
|
+
push(item) {
|
|
28778
|
+
if (this.#closed) return;
|
|
28779
|
+
this.items.push(item);
|
|
28780
|
+
this.#wake?.();
|
|
28781
|
+
}
|
|
28782
|
+
/** The next message; null once closed. */
|
|
28783
|
+
async next() {
|
|
28784
|
+
for (; ; ) {
|
|
28785
|
+
if (this.#closed) return null;
|
|
28786
|
+
const item = this.items.shift();
|
|
28787
|
+
if (item !== void 0) return item;
|
|
28788
|
+
await new Promise((resolve) => this.#wake = resolve);
|
|
28789
|
+
this.#wake = null;
|
|
28790
|
+
}
|
|
28791
|
+
}
|
|
28792
|
+
/** Stops taking messages; returns those still queued. */
|
|
28793
|
+
close() {
|
|
28794
|
+
this.#closed = true;
|
|
28795
|
+
const dropped = this.items.splice(0);
|
|
28796
|
+
this.#wake?.();
|
|
28797
|
+
return dropped;
|
|
28798
|
+
}
|
|
28799
|
+
};
|
|
28766
28800
|
var MAX_CELLS = 1e3;
|
|
28801
|
+
function subshellNotFound(evalue) {
|
|
28802
|
+
return { status: "error", ename: "SubshellNotFound", evalue, traceback: [`SubshellNotFound: ${evalue}`] };
|
|
28803
|
+
}
|
|
28767
28804
|
var SHELL_REPLIES = {
|
|
28768
28805
|
kernel_info_request: "kernel_info_reply",
|
|
28769
28806
|
complete_request: "complete_reply",
|
|
@@ -28815,13 +28852,16 @@ var KernelCore = class {
|
|
|
28815
28852
|
#executionCount = 0;
|
|
28816
28853
|
#parent = {};
|
|
28817
28854
|
#allowStdin = false;
|
|
28818
|
-
|
|
28819
|
-
|
|
28820
|
-
|
|
28821
|
-
|
|
28822
|
-
|
|
28823
|
-
#abortQueued = 0;
|
|
28855
|
+
/** Cells and comm handlers running in the target. */
|
|
28856
|
+
#running = 0;
|
|
28857
|
+
/** A cell is running: its parent header and allow_stdin hold until it ends (#417). */
|
|
28858
|
+
#cellRunning = false;
|
|
28859
|
+
/** stop_on_error (#123): the message being handled was queued behind a failed cell. */
|
|
28824
28860
|
#aborting = false;
|
|
28861
|
+
/** Messages without a subshell_id, in the order they came. */
|
|
28862
|
+
#mainShell = new ShellQueue();
|
|
28863
|
+
/** Kernel subshells (JEP 91, #417): subshell_id -> its queue. */
|
|
28864
|
+
#subshells = /* @__PURE__ */ new Map();
|
|
28825
28865
|
/** The input_request waiting for its input_reply, if any. */
|
|
28826
28866
|
#input = null;
|
|
28827
28867
|
/** An interrupt is waiting on the target. */
|
|
@@ -28845,8 +28885,10 @@ var KernelCore = class {
|
|
|
28845
28885
|
async run() {
|
|
28846
28886
|
this.#ensureTarget().catch((err) => this.#log(`target failed to start: ${err}`));
|
|
28847
28887
|
if (typeof this.#typeStrip === "string") await loadTypeStripper(this.#typeStrip);
|
|
28888
|
+
await this.#channels.ready;
|
|
28848
28889
|
await Promise.all([
|
|
28849
|
-
this.#
|
|
28890
|
+
this.#readShell(),
|
|
28891
|
+
this.#runShell(this.#mainShell),
|
|
28850
28892
|
this.#loop("control", (m, p) => this.#handleControl(m, p)),
|
|
28851
28893
|
this.#loop("stdin", (m) => this.#handleStdin(m))
|
|
28852
28894
|
]);
|
|
@@ -28870,8 +28912,9 @@ var KernelCore = class {
|
|
|
28870
28912
|
if (target?.diagnose) targetState = await target.diagnose().catch((err) => `diagnose failed: ${err}`);
|
|
28871
28913
|
this.#log(`state: ${JSON.stringify({
|
|
28872
28914
|
shell: handling && { msgType: handling.msgType, msgId: handling.msgId, ms: Date.now() - handling.since },
|
|
28873
|
-
queued: this.#channels.shellQueued(),
|
|
28874
|
-
|
|
28915
|
+
queued: this.#mainShell.items.length + this.#channels.shellQueued(),
|
|
28916
|
+
subshells: this.#subshells.size,
|
|
28917
|
+
running: this.#running,
|
|
28875
28918
|
interrupting: this.#interrupting,
|
|
28876
28919
|
awaitingInput: this.#input !== null,
|
|
28877
28920
|
target: targetState
|
|
@@ -28900,25 +28943,28 @@ var KernelCore = class {
|
|
|
28900
28943
|
const type = msg.header.msg_type;
|
|
28901
28944
|
const commId = String(msg.content.comm_id ?? "");
|
|
28902
28945
|
const target = await this.#ensureTarget();
|
|
28903
|
-
this.#
|
|
28904
|
-
|
|
28905
|
-
|
|
28946
|
+
if (!this.#cellRunning) {
|
|
28947
|
+
this.#parent = msg.header;
|
|
28948
|
+
this.#allowStdin = false;
|
|
28949
|
+
}
|
|
28950
|
+
const parent = msg.header;
|
|
28906
28951
|
let handled = false;
|
|
28952
|
+
this.#running++;
|
|
28907
28953
|
try {
|
|
28908
28954
|
const result = await target.dispatchComm(type, msg.content, msg.metadata, msg.buffers);
|
|
28909
28955
|
if ("error" in result) {
|
|
28910
28956
|
const { name, message, stack } = result.error;
|
|
28911
28957
|
this.#publish("stream", { name: "stderr", text: `Error in ${type} handler: ${stack || `${name}: ${message}`}
|
|
28912
|
-
` });
|
|
28958
|
+
` }, { parent });
|
|
28913
28959
|
} else {
|
|
28914
28960
|
handled = result.handled;
|
|
28915
28961
|
}
|
|
28916
28962
|
} catch (err) {
|
|
28917
28963
|
if (!(err instanceof Interrupted)) throw err;
|
|
28918
28964
|
this.#publish("stream", { name: "stderr", text: `${type} handler interrupted
|
|
28919
|
-
` });
|
|
28965
|
+
` }, { parent });
|
|
28920
28966
|
} finally {
|
|
28921
|
-
this.#
|
|
28967
|
+
this.#running--;
|
|
28922
28968
|
}
|
|
28923
28969
|
await target.flush().catch(() => {
|
|
28924
28970
|
});
|
|
@@ -28926,7 +28972,7 @@ var KernelCore = class {
|
|
|
28926
28972
|
if (handled) {
|
|
28927
28973
|
this.#comms.set(commId, String(msg.content.target_name ?? ""));
|
|
28928
28974
|
} else {
|
|
28929
|
-
this.#publish("comm_close", { comm_id: commId, data: {} });
|
|
28975
|
+
this.#publish("comm_close", { comm_id: commId, data: {} }, { parent });
|
|
28930
28976
|
}
|
|
28931
28977
|
} else if (type === "comm_close") {
|
|
28932
28978
|
this.#comms.delete(commId);
|
|
@@ -28942,6 +28988,7 @@ var KernelCore = class {
|
|
|
28942
28988
|
return target;
|
|
28943
28989
|
}, (err) => {
|
|
28944
28990
|
this.#targetStarting = null;
|
|
28991
|
+
if (typeof err === "object" && err !== null) launchFailures.add(err);
|
|
28945
28992
|
throw err;
|
|
28946
28993
|
});
|
|
28947
28994
|
return this.#targetStarting;
|
|
@@ -28961,10 +29008,18 @@ var KernelCore = class {
|
|
|
28961
29008
|
this.#interruptStart = null;
|
|
28962
29009
|
}
|
|
28963
29010
|
}
|
|
29011
|
+
/** Tells the host of a fault in the kernel's own code; a target that failed to launch isn't one (#422). */
|
|
29012
|
+
#fault(err, where) {
|
|
29013
|
+
if (typeof err === "object" && err !== null && launchFailures.has(err)) return;
|
|
29014
|
+
this.#host.fault?.(err, where);
|
|
29015
|
+
}
|
|
28964
29016
|
#targetEvents() {
|
|
28965
29017
|
return {
|
|
28966
29018
|
stream: (name, text) => this.#publish("stream", { name, text }),
|
|
28967
|
-
message: (msg) => void this.#onTargetMessage(msg).catch((err) =>
|
|
29019
|
+
message: (msg) => void this.#onTargetMessage(msg).catch((err) => {
|
|
29020
|
+
this.#log(`error handling target message: ${err}`);
|
|
29021
|
+
this.#fault(err, "target message");
|
|
29022
|
+
}),
|
|
28968
29023
|
exit: (code, note) => {
|
|
28969
29024
|
this.#target = null;
|
|
28970
29025
|
this.#types?.reset();
|
|
@@ -29007,7 +29062,7 @@ ${text}
|
|
|
29007
29062
|
this.#interruptStart();
|
|
29008
29063
|
return;
|
|
29009
29064
|
}
|
|
29010
|
-
if (!this.#target ||
|
|
29065
|
+
if (!this.#target || this.#running === 0) return;
|
|
29011
29066
|
this.#interrupting = true;
|
|
29012
29067
|
try {
|
|
29013
29068
|
await this.#target.interrupt();
|
|
@@ -29037,19 +29092,70 @@ ${text}
|
|
|
29037
29092
|
async #loop(channel, handle) {
|
|
29038
29093
|
while (!this.#shuttingDown) {
|
|
29039
29094
|
const received = await this.#channels.recv(channel);
|
|
29040
|
-
if (
|
|
29041
|
-
|
|
29042
|
-
|
|
29095
|
+
if (received === null) continue;
|
|
29096
|
+
try {
|
|
29097
|
+
await handle(received.msg, received.peer);
|
|
29098
|
+
} catch (err) {
|
|
29099
|
+
this.#log(`error handling message: ${err instanceof Error ? err.stack : err}`);
|
|
29100
|
+
this.#fault(err, `${channel} handler`);
|
|
29043
29101
|
}
|
|
29102
|
+
}
|
|
29103
|
+
}
|
|
29104
|
+
/**
|
|
29105
|
+
* Takes every shell message as it comes and queues it for the main shell
|
|
29106
|
+
* or its subshell, so a subshell's message isn't stuck behind a running
|
|
29107
|
+
* cell (#417).
|
|
29108
|
+
*/
|
|
29109
|
+
async #readShell() {
|
|
29110
|
+
while (!this.#shuttingDown) {
|
|
29111
|
+
const received = await this.#channels.recv("shell");
|
|
29044
29112
|
if (received === null) continue;
|
|
29045
|
-
const
|
|
29113
|
+
const subshellId = received.msg.header.subshell_id;
|
|
29114
|
+
if (typeof subshellId !== "string") {
|
|
29115
|
+
this.#mainShell.push({ ...received, abort: false });
|
|
29116
|
+
continue;
|
|
29117
|
+
}
|
|
29118
|
+
const queue = this.#subshells.get(subshellId);
|
|
29119
|
+
if (queue === void 0) {
|
|
29120
|
+
this.#refuseShell(received, `No subshell with id ${subshellId}`);
|
|
29121
|
+
} else if (received.msg.header.msg_type === "execute_request") {
|
|
29122
|
+
this.#mainShell.push({ ...received, abort: false });
|
|
29123
|
+
} else {
|
|
29124
|
+
queue.push({ ...received, abort: false });
|
|
29125
|
+
}
|
|
29126
|
+
}
|
|
29127
|
+
}
|
|
29128
|
+
/**
|
|
29129
|
+
* Answers a shell message for a subshell that doesn't exist, or was
|
|
29130
|
+
* deleted with the message queued, so the frontend doesn't wait on it.
|
|
29131
|
+
*/
|
|
29132
|
+
#refuseShell({ peer, msg }, evalue) {
|
|
29133
|
+
const type = msg.header.msg_type;
|
|
29134
|
+
this.#log(`refusing ${type}: ${evalue}`);
|
|
29135
|
+
this.#status("busy", msg.header);
|
|
29136
|
+
const replyType = type === "execute_request" ? "execute_reply" : SHELL_REPLIES[type];
|
|
29137
|
+
if (replyType !== void 0) this.#reply("shell", peer, msg, replyType, subshellNotFound(evalue));
|
|
29138
|
+
if (type === "comm_open") this.#publish("comm_close", { comm_id: String(msg.content.comm_id ?? ""), data: {} }, { parent: msg.header });
|
|
29139
|
+
this.#status("idle", msg.header);
|
|
29140
|
+
}
|
|
29141
|
+
/** Handles one queue's messages in turn. */
|
|
29142
|
+
async #runShell(queue) {
|
|
29143
|
+
const main = queue === this.#mainShell;
|
|
29144
|
+
while (!this.#shuttingDown) {
|
|
29145
|
+
const queued = await queue.next();
|
|
29146
|
+
if (queued === null) return;
|
|
29147
|
+
const { peer, msg } = queued;
|
|
29046
29148
|
try {
|
|
29047
|
-
if (
|
|
29048
|
-
|
|
29149
|
+
if (main) {
|
|
29150
|
+
this.#aborting = queued.abort;
|
|
29151
|
+
this.#handling = { msgType: msg.header.msg_type, msgId: msg.header.msg_id, since: Date.now() };
|
|
29152
|
+
}
|
|
29153
|
+
await this.#handleShell(msg, peer);
|
|
29049
29154
|
} catch (err) {
|
|
29050
29155
|
this.#log(`error handling message: ${err instanceof Error ? err.stack : err}`);
|
|
29156
|
+
this.#fault(err, "shell handler");
|
|
29051
29157
|
} finally {
|
|
29052
|
-
if (
|
|
29158
|
+
if (main) this.#handling = null;
|
|
29053
29159
|
}
|
|
29054
29160
|
}
|
|
29055
29161
|
}
|
|
@@ -29063,7 +29169,12 @@ ${text}
|
|
|
29063
29169
|
language_info: {
|
|
29064
29170
|
name: "typescript",
|
|
29065
29171
|
version: this.#host.languageVersion ?? TYPESCRIPT_VERSION,
|
|
29066
|
-
|
|
29172
|
+
// JupyterLab's LSP adapter picks the language server by a language
|
|
29173
|
+
// it derives from this MIME type, not from name: it drops the type
|
|
29174
|
+
// and an "x-" prefix, so "text/x.typescript" became "x.typescript"
|
|
29175
|
+
// and matched no server (#400). This is CodeMirror's MIME type for
|
|
29176
|
+
// TypeScript and in jupyter-lsp's typescript-language-server spec.
|
|
29177
|
+
mimetype: "application/typescript",
|
|
29067
29178
|
file_extension: ".ts",
|
|
29068
29179
|
pygments_lexer: "typescript",
|
|
29069
29180
|
codemirror_mode: "typescript",
|
|
@@ -29075,12 +29186,19 @@ ${text}
|
|
|
29075
29186
|
debugger: this.#debugger !== null,
|
|
29076
29187
|
// What current ipykernel advertises; JupyterLab itself goes by the
|
|
29077
29188
|
// kernelspec's metadata.debugger.
|
|
29078
|
-
supported_features: this.#debugger !== null ? ["debugger"] : [],
|
|
29189
|
+
supported_features: [...this.#debugger !== null ? ["debugger"] : [], "kernel subshells"],
|
|
29079
29190
|
...this.#host.capabilities ? { capabilities: this.#host.capabilities } : {}
|
|
29080
29191
|
};
|
|
29081
29192
|
}
|
|
29082
29193
|
// --- control channel ------------------------------------------------------
|
|
29083
29194
|
async #handleControl(msg, peer) {
|
|
29195
|
+
if (msg.header.msg_type === "usage_request") {
|
|
29196
|
+
void this.#handleControlRequest(msg, peer).catch((err) => this.#log(`usage_request failed: ${err}`));
|
|
29197
|
+
return;
|
|
29198
|
+
}
|
|
29199
|
+
return this.#handleControlRequest(msg, peer);
|
|
29200
|
+
}
|
|
29201
|
+
async #handleControlRequest(msg, peer) {
|
|
29084
29202
|
this.#status("busy", msg.header);
|
|
29085
29203
|
try {
|
|
29086
29204
|
await this.#controlRequest("control", msg, peer);
|
|
@@ -29101,6 +29219,37 @@ ${text}
|
|
|
29101
29219
|
]);
|
|
29102
29220
|
this.#reply(channel, peer, msg, "interrupt_reply", { status: "ok" });
|
|
29103
29221
|
break;
|
|
29222
|
+
case "create_subshell_request": {
|
|
29223
|
+
const subshellId = crypto.randomUUID();
|
|
29224
|
+
const queue = new ShellQueue();
|
|
29225
|
+
this.#subshells.set(subshellId, queue);
|
|
29226
|
+
void this.#runShell(queue);
|
|
29227
|
+
this.#reply(channel, peer, msg, "create_subshell_reply", { status: "ok", subshell_id: subshellId });
|
|
29228
|
+
break;
|
|
29229
|
+
}
|
|
29230
|
+
case "delete_subshell_request": {
|
|
29231
|
+
const subshellId = String(msg.content.subshell_id ?? "");
|
|
29232
|
+
const queue = this.#subshells.get(subshellId);
|
|
29233
|
+
if (queue === void 0) {
|
|
29234
|
+
this.#reply(channel, peer, msg, "delete_subshell_reply", subshellNotFound(`No subshell with id ${subshellId}`));
|
|
29235
|
+
break;
|
|
29236
|
+
}
|
|
29237
|
+
this.#subshells.delete(subshellId);
|
|
29238
|
+
for (const dropped of queue.close()) this.#refuseShell(dropped, `Subshell ${subshellId} was deleted`);
|
|
29239
|
+
this.#reply(channel, peer, msg, "delete_subshell_reply", { status: "ok" });
|
|
29240
|
+
break;
|
|
29241
|
+
}
|
|
29242
|
+
case "list_subshell_request":
|
|
29243
|
+
this.#reply(channel, peer, msg, "list_subshell_reply", { status: "ok", subshell_id: [...this.#subshells.keys()] });
|
|
29244
|
+
break;
|
|
29245
|
+
case "usage_request": {
|
|
29246
|
+
const usage = this.#host.usage?.(this.#target).catch((err) => {
|
|
29247
|
+
this.#log(`usage_request failed: ${err}`);
|
|
29248
|
+
return {};
|
|
29249
|
+
});
|
|
29250
|
+
this.#reply(channel, peer, msg, "usage_reply", await usage ?? {});
|
|
29251
|
+
break;
|
|
29252
|
+
}
|
|
29104
29253
|
case "debug_request": {
|
|
29105
29254
|
let reply;
|
|
29106
29255
|
if (this.#debugger === null) {
|
|
@@ -29375,7 +29524,8 @@ ${expression}
|
|
|
29375
29524
|
let error = null;
|
|
29376
29525
|
let userExpressions = {};
|
|
29377
29526
|
let structured = null;
|
|
29378
|
-
this.#
|
|
29527
|
+
this.#running++;
|
|
29528
|
+
this.#cellRunning = true;
|
|
29379
29529
|
try {
|
|
29380
29530
|
const target = await this.#targetForCell();
|
|
29381
29531
|
if (target.notice !== void 0 && this.#noticeShownFor !== target) {
|
|
@@ -29416,15 +29566,16 @@ ${expression}
|
|
|
29416
29566
|
error = { ename: "KernelError", evalue: message, traceback: [message] };
|
|
29417
29567
|
}
|
|
29418
29568
|
} finally {
|
|
29419
|
-
this.#
|
|
29569
|
+
this.#running--;
|
|
29570
|
+
this.#cellRunning = false;
|
|
29420
29571
|
}
|
|
29421
29572
|
await this.#target?.releaseResults?.();
|
|
29422
29573
|
if (error) {
|
|
29423
29574
|
if (!silent && msg.content.stop_on_error !== false) {
|
|
29424
29575
|
await new Promise((r) => setTimeout(r, 0));
|
|
29425
|
-
|
|
29576
|
+
for (const queued of this.#mainShell.items) queued.abort = true;
|
|
29426
29577
|
}
|
|
29427
|
-
this.#publish("error", error, structured ? { metadata: { [TRACEBACK_MIME]: structured } } : {});
|
|
29578
|
+
this.#publish("error", error, { parent, ...structured ? { metadata: { [TRACEBACK_MIME]: structured } } : {} });
|
|
29428
29579
|
this.#reply("shell", peer, msg, "execute_reply", { status: "error", execution_count: count, ...error });
|
|
29429
29580
|
} else {
|
|
29430
29581
|
this.#reply("shell", peer, msg, "execute_reply", {
|
|
@@ -29439,7 +29590,7 @@ ${expression}
|
|
|
29439
29590
|
};
|
|
29440
29591
|
|
|
29441
29592
|
// stub:package
|
|
29442
|
-
var VERSION = "0.
|
|
29593
|
+
var VERSION = "0.9.0";
|
|
29443
29594
|
|
|
29444
29595
|
// src/browser/channels.ts
|
|
29445
29596
|
var PEER = "page";
|
|
@@ -29558,7 +29709,10 @@ var BrowserTarget = class _BrowserTarget {
|
|
|
29558
29709
|
#hostCalls = /* @__PURE__ */ new Map();
|
|
29559
29710
|
#host;
|
|
29560
29711
|
#nextId = 0;
|
|
29561
|
-
|
|
29712
|
+
/** Counts interrupt() calls: a call that saw one start during it was interrupted (#417). */
|
|
29713
|
+
#interrupts = 0;
|
|
29714
|
+
/** Cells running: a comm handler that starts with none gets its own jupyter.signal (#421). */
|
|
29715
|
+
#cells = 0;
|
|
29562
29716
|
#stopNote;
|
|
29563
29717
|
#exited = false;
|
|
29564
29718
|
constructor(worker, events, host) {
|
|
@@ -29662,26 +29816,33 @@ var BrowserTarget = class _BrowserTarget {
|
|
|
29662
29816
|
});
|
|
29663
29817
|
}
|
|
29664
29818
|
async #interruptibly(op, params, what) {
|
|
29665
|
-
|
|
29819
|
+
const interrupts = this.#interrupts;
|
|
29666
29820
|
try {
|
|
29667
29821
|
return await this.#request(op, params, true);
|
|
29668
29822
|
} catch (err) {
|
|
29669
|
-
if (err instanceof Abandoned || this.#
|
|
29823
|
+
if (err instanceof Abandoned || this.#interrupts !== interrupts) throw new Interrupted(`${what} interrupted`);
|
|
29670
29824
|
throw err;
|
|
29671
29825
|
}
|
|
29672
29826
|
}
|
|
29673
29827
|
async evaluate(script) {
|
|
29674
|
-
|
|
29828
|
+
this.#cells++;
|
|
29829
|
+
try {
|
|
29830
|
+
return asEvaluateResult(await this.#interruptibly("eval", { code: script }, "Execution"));
|
|
29831
|
+
} finally {
|
|
29832
|
+
this.#cells--;
|
|
29833
|
+
}
|
|
29675
29834
|
}
|
|
29676
29835
|
/**
|
|
29677
29836
|
* A cell that's waiting on something leaves the Worker free: it answers a
|
|
29678
29837
|
* ping, and the cell is abandoned with its state intact; host requests
|
|
29679
29838
|
* in flight are cancelled on the page, and reject in the Worker with an
|
|
29680
|
-
* AbortError (#388)
|
|
29839
|
+
* AbortError (#388), and jupyter.signal is aborted (#418). A busy cell
|
|
29840
|
+
* can't be reached, so the Worker is
|
|
29681
29841
|
* terminated, and a new one starts on the next cell.
|
|
29682
29842
|
*/
|
|
29683
29843
|
async interrupt() {
|
|
29684
|
-
this.#
|
|
29844
|
+
this.#interrupts++;
|
|
29845
|
+
const cellRunning = this.#cells > 0;
|
|
29685
29846
|
const running = [...this.#interruptible];
|
|
29686
29847
|
const answered = await Promise.race([
|
|
29687
29848
|
this.#request("ping").then(() => true, () => false),
|
|
@@ -29694,6 +29855,8 @@ var BrowserTarget = class _BrowserTarget {
|
|
|
29694
29855
|
this.#interruptible.delete(id);
|
|
29695
29856
|
}
|
|
29696
29857
|
this.#cancelHostCalls();
|
|
29858
|
+
void this.#request("abort", { cell: cellRunning }).catch(() => {
|
|
29859
|
+
});
|
|
29697
29860
|
return;
|
|
29698
29861
|
}
|
|
29699
29862
|
this.#stopNote = RESTART_NOTE;
|
|
@@ -29708,7 +29871,13 @@ var BrowserTarget = class _BrowserTarget {
|
|
|
29708
29871
|
await this.#request("broadcast", { count: executionCount, handle: result.objectId });
|
|
29709
29872
|
}
|
|
29710
29873
|
async dispatchComm(msgType, content, metadata, buffers) {
|
|
29711
|
-
const reply = await this.#interruptibly("comm", {
|
|
29874
|
+
const reply = await this.#interruptibly("comm", {
|
|
29875
|
+
msgType,
|
|
29876
|
+
content,
|
|
29877
|
+
metadata,
|
|
29878
|
+
buffers: buffers.map(toBase64),
|
|
29879
|
+
ownSignal: this.#cells === 0
|
|
29880
|
+
}, "Comm handler");
|
|
29712
29881
|
if (isRecord(reply.error)) {
|
|
29713
29882
|
const { name, message, stack } = reply.error;
|
|
29714
29883
|
return { error: { name: String(name), message: String(message), stack: String(stack) } };
|