@tlockney/cdp-kernel 0.6.0 → 0.7.1
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 +5 -3
- package/dist/browser/channels.d.ts +27 -0
- package/dist/browser/channels.js +90 -0
- package/dist/browser/kernel.js +29800 -0
- package/dist/browser/kernel.js.map +7 -0
- package/dist/browser/mod.d.ts +25 -0
- package/dist/browser/mod.js +41 -0
- package/dist/browser/target.d.ts +94 -0
- package/dist/browser/target.js +264 -0
- package/dist/browser/worker.js +1071 -0
- package/dist/browser/worker.js.map +7 -0
- package/dist/bun-target.d.ts +2 -0
- package/dist/bun-target.js +15 -2
- package/dist/cdp.d.ts +11 -0
- package/dist/cdp.js +34 -7
- package/dist/celld-target.js +3 -2
- package/dist/debugger.d.ts +2 -0
- package/dist/debugger.js +63 -11
- package/dist/kernel-core.d.ts +78 -0
- package/dist/kernel-core.js +824 -0
- package/dist/kernel.d.ts +6 -1
- package/dist/kernel.js +104 -723
- package/dist/main.js +11 -4
- package/dist/message.d.ts +34 -0
- package/dist/message.js +14 -0
- package/dist/package.d.ts +2 -2
- package/dist/package.js +2 -2
- package/dist/target-api.d.ts +92 -0
- package/dist/target-api.js +48 -0
- package/dist/target.d.ts +5 -76
- package/dist/target.js +62 -33
- package/dist/traceback.d.ts +75 -0
- package/dist/traceback.js +200 -0
- package/dist/transform.d.ts +1 -0
- package/dist/transform.js +8 -1
- package/dist/wire.d.ts +4 -24
- package/dist/wire.js +3 -12
- package/dist/workerd-target.d.ts +6 -1
- package/dist/workerd-target.js +56 -12
- package/dist/workers-project.d.ts +1 -1
- package/dist/workers-project.js +4 -3
- package/dist/zmq-channels.d.ts +14 -0
- package/dist/zmq-channels.js +59 -0
- package/package.json +9 -2
- package/runtime/bootstrap.mjs +2 -0
- package/runtime/browser-worker.mjs +202 -0
- package/runtime/cdn.d.mts +2 -0
- package/runtime/cdn.mjs +17 -0
- package/runtime/display.mjs +202 -1
- package/runtime/evaluator.mjs +2 -0
- package/runtime/format.d.mts +2 -0
- package/runtime/format.mjs +125 -0
- package/runtime/workerd-worker.mjs +2 -0
|
@@ -0,0 +1,1071 @@
|
|
|
1
|
+
// runtime/comm.mjs
|
|
2
|
+
var Comm = class {
|
|
3
|
+
#send;
|
|
4
|
+
#onClosed;
|
|
5
|
+
#msgHandlers = [];
|
|
6
|
+
#closeHandlers = [];
|
|
7
|
+
closed = false;
|
|
8
|
+
constructor(id, targetName, send, onClosed) {
|
|
9
|
+
this.id = id;
|
|
10
|
+
this.targetName = targetName;
|
|
11
|
+
this.#send = send;
|
|
12
|
+
this.#onClosed = onClosed;
|
|
13
|
+
}
|
|
14
|
+
send(data = {}, { metadata = {}, buffers = [] } = {}) {
|
|
15
|
+
if (this.closed) return;
|
|
16
|
+
this.#send("comm_msg", { comm_id: this.id, data }, metadata, buffers);
|
|
17
|
+
}
|
|
18
|
+
close(data = {}, { metadata = {}, buffers = [] } = {}) {
|
|
19
|
+
if (this.closed) return;
|
|
20
|
+
this.#send("comm_close", { comm_id: this.id, data }, metadata, buffers);
|
|
21
|
+
void this._closed({ data, metadata, buffers });
|
|
22
|
+
}
|
|
23
|
+
onMsg(handler) {
|
|
24
|
+
this.#msgHandlers.push(handler);
|
|
25
|
+
}
|
|
26
|
+
onClose(handler) {
|
|
27
|
+
this.#closeHandlers.push(handler);
|
|
28
|
+
}
|
|
29
|
+
async _receive(msg) {
|
|
30
|
+
for (const handler of this.#msgHandlers) await handler(msg);
|
|
31
|
+
}
|
|
32
|
+
async _closed(msg) {
|
|
33
|
+
if (this.closed) return;
|
|
34
|
+
this.closed = true;
|
|
35
|
+
this.#onClosed(this.id);
|
|
36
|
+
for (const handler of this.#closeHandlers) await handler(msg);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
function createComms(send, newId = () => crypto.randomUUID()) {
|
|
40
|
+
const comms = /* @__PURE__ */ new Map();
|
|
41
|
+
const targets = /* @__PURE__ */ new Map();
|
|
42
|
+
const forget = (id) => comms.delete(id);
|
|
43
|
+
function track(id, targetName) {
|
|
44
|
+
const comm = new Comm(id, targetName, send, forget);
|
|
45
|
+
comms.set(id, comm);
|
|
46
|
+
return comm;
|
|
47
|
+
}
|
|
48
|
+
const api = {
|
|
49
|
+
open(targetName, data = {}, { metadata = {}, buffers = [] } = {}) {
|
|
50
|
+
const comm = track(newId(), targetName);
|
|
51
|
+
send("comm_open", { comm_id: comm.id, target_name: targetName, data }, metadata, buffers);
|
|
52
|
+
return comm;
|
|
53
|
+
},
|
|
54
|
+
registerTarget(targetName, handler) {
|
|
55
|
+
targets.set(targetName, handler);
|
|
56
|
+
},
|
|
57
|
+
unregisterTarget(targetName) {
|
|
58
|
+
targets.delete(targetName);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
async function dispatch(msgType, content, metadata, buffers) {
|
|
62
|
+
const msg = { data: content.data ?? {}, metadata: metadata ?? {}, buffers: buffers ?? [] };
|
|
63
|
+
if (msgType === "comm_open") {
|
|
64
|
+
const handler = targets.get(content.target_name);
|
|
65
|
+
if (!handler) return false;
|
|
66
|
+
const comm2 = track(content.comm_id, content.target_name);
|
|
67
|
+
try {
|
|
68
|
+
await handler(comm2, msg);
|
|
69
|
+
} catch (err) {
|
|
70
|
+
comm2.closed = true;
|
|
71
|
+
forget(comm2.id);
|
|
72
|
+
throw err;
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
const comm = comms.get(content.comm_id);
|
|
77
|
+
if (!comm) return false;
|
|
78
|
+
if (msgType === "comm_msg") await comm._receive(msg);
|
|
79
|
+
else if (msgType === "comm_close") await comm._closed(msg);
|
|
80
|
+
else return false;
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
function list2() {
|
|
84
|
+
return [...comms.values()].map((comm) => ({ commId: comm.id, targetName: comm.targetName }));
|
|
85
|
+
}
|
|
86
|
+
return { api, dispatch, list: list2 };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// runtime/widget.mjs
|
|
90
|
+
var WIDGET_PROTOCOL_VERSION = "2.1.0";
|
|
91
|
+
var WIDGET_TARGET = "jupyter.widget";
|
|
92
|
+
var CONTROL_TARGET = "jupyter.widget.control";
|
|
93
|
+
var VIEW_MIME = "application/vnd.jupyter.widget-view+json";
|
|
94
|
+
var ANYWIDGET_MODEL = {
|
|
95
|
+
_model_name: "AnyModel",
|
|
96
|
+
_model_module: "anywidget",
|
|
97
|
+
_model_module_version: "*",
|
|
98
|
+
_view_name: "AnyView",
|
|
99
|
+
_view_module: "anywidget",
|
|
100
|
+
_view_module_version: "*",
|
|
101
|
+
_view_count: null
|
|
102
|
+
};
|
|
103
|
+
function isBinary(value) {
|
|
104
|
+
return value instanceof Uint8Array || value instanceof ArrayBuffer || ArrayBuffer.isView(value);
|
|
105
|
+
}
|
|
106
|
+
function toBytes(value) {
|
|
107
|
+
if (value instanceof Uint8Array) return value;
|
|
108
|
+
if (value instanceof ArrayBuffer) return new Uint8Array(value);
|
|
109
|
+
return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
|
|
110
|
+
}
|
|
111
|
+
function removeBuffers(state) {
|
|
112
|
+
const bufferPaths = [];
|
|
113
|
+
const buffers = [];
|
|
114
|
+
function walk(value, path) {
|
|
115
|
+
if (isBinary(value)) {
|
|
116
|
+
bufferPaths.push(path);
|
|
117
|
+
buffers.push(toBytes(value));
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
if (Array.isArray(value)) return value.map((item, i) => walk(item, [...path, i]));
|
|
121
|
+
if (value !== null && typeof value === "object") {
|
|
122
|
+
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, walk(v, [...path, k])]));
|
|
123
|
+
}
|
|
124
|
+
return value;
|
|
125
|
+
}
|
|
126
|
+
return { state: walk(state, []), bufferPaths, buffers };
|
|
127
|
+
}
|
|
128
|
+
function putBuffers(state, bufferPaths = [], buffers = []) {
|
|
129
|
+
bufferPaths.forEach((path, i) => {
|
|
130
|
+
let obj = state;
|
|
131
|
+
for (const key2 of path.slice(0, -1)) obj = obj[key2];
|
|
132
|
+
obj[path[path.length - 1]] = buffers[i];
|
|
133
|
+
});
|
|
134
|
+
return state;
|
|
135
|
+
}
|
|
136
|
+
var Widget = class {
|
|
137
|
+
#comm;
|
|
138
|
+
#state;
|
|
139
|
+
#listeners = /* @__PURE__ */ new Map();
|
|
140
|
+
// event -> Set<listener>
|
|
141
|
+
constructor(comm, state, $display2) {
|
|
142
|
+
this.#comm = comm;
|
|
143
|
+
this.#state = state;
|
|
144
|
+
this[$display2] = () => ({
|
|
145
|
+
[VIEW_MIME]: { version_major: 2, version_minor: 1, model_id: this.id },
|
|
146
|
+
"text/plain": `Widget(${this.id})`
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
get id() {
|
|
150
|
+
return this.#comm.id;
|
|
151
|
+
}
|
|
152
|
+
get closed() {
|
|
153
|
+
return this.#comm.closed;
|
|
154
|
+
}
|
|
155
|
+
get(key2) {
|
|
156
|
+
return this.#state[key2];
|
|
157
|
+
}
|
|
158
|
+
/** set("key", value) or set({ key: value, ... }); syncs to the frontend. */
|
|
159
|
+
set(keyOrChanges, value) {
|
|
160
|
+
const changes = typeof keyOrChanges === "string" ? { [keyOrChanges]: value } : keyOrChanges;
|
|
161
|
+
this.#apply(changes);
|
|
162
|
+
if (this.closed) return;
|
|
163
|
+
const { state, bufferPaths, buffers } = removeBuffers(changes);
|
|
164
|
+
this.#comm.send({ method: "update", state, buffer_paths: bufferPaths }, { buffers });
|
|
165
|
+
}
|
|
166
|
+
on(event, listener) {
|
|
167
|
+
if (!this.#listeners.has(event)) this.#listeners.set(event, /* @__PURE__ */ new Set());
|
|
168
|
+
this.#listeners.get(event).add(listener);
|
|
169
|
+
}
|
|
170
|
+
off(event, listener) {
|
|
171
|
+
this.#listeners.get(event)?.delete(listener);
|
|
172
|
+
}
|
|
173
|
+
/** A custom message, delivered to the view's model.on("msg:custom"). */
|
|
174
|
+
send(content, buffers = []) {
|
|
175
|
+
this.#comm.send({ method: "custom", content }, { buffers });
|
|
176
|
+
}
|
|
177
|
+
close() {
|
|
178
|
+
this.#comm.close();
|
|
179
|
+
}
|
|
180
|
+
/** The full state, as the frontend sees it (for request_state). */
|
|
181
|
+
fullState() {
|
|
182
|
+
return { ...ANYWIDGET_MODEL, ...this.#state };
|
|
183
|
+
}
|
|
184
|
+
async #emit(event, ...args) {
|
|
185
|
+
for (const listener of this.#listeners.get(event) ?? []) await listener(...args);
|
|
186
|
+
}
|
|
187
|
+
async #apply(changes) {
|
|
188
|
+
const previous = {};
|
|
189
|
+
for (const [key2, value] of Object.entries(changes)) {
|
|
190
|
+
previous[key2] = this.#state[key2];
|
|
191
|
+
this.#state[key2] = value;
|
|
192
|
+
}
|
|
193
|
+
for (const key2 of Object.keys(changes)) await this.#emit(`change:${key2}`, changes[key2], previous[key2]);
|
|
194
|
+
await this.#emit("change", changes);
|
|
195
|
+
}
|
|
196
|
+
async _receive(msg) {
|
|
197
|
+
const { method } = msg.data;
|
|
198
|
+
if (method === "update") {
|
|
199
|
+
const changes = putBuffers(msg.data.state ?? {}, msg.data.buffer_paths, msg.buffers);
|
|
200
|
+
await this.#apply(changes);
|
|
201
|
+
} else if (method === "request_state") {
|
|
202
|
+
const { state, bufferPaths, buffers } = removeBuffers(this.fullState());
|
|
203
|
+
this.#comm.send({ method: "update", state, buffer_paths: bufferPaths }, { buffers });
|
|
204
|
+
} else if (method === "custom") {
|
|
205
|
+
await this.#emit("msg:custom", msg.data.content, msg.buffers);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
function createWidgetFactory(commApi, $display2) {
|
|
210
|
+
const live = /* @__PURE__ */ new Map();
|
|
211
|
+
commApi.registerTarget(CONTROL_TARGET, (control) => {
|
|
212
|
+
control.onMsg((msg) => {
|
|
213
|
+
if (msg.data.method !== "request_states") return;
|
|
214
|
+
const states = {};
|
|
215
|
+
for (const widget of live.values()) {
|
|
216
|
+
const full = widget.fullState();
|
|
217
|
+
states[widget.id] = {
|
|
218
|
+
model_name: full._model_name,
|
|
219
|
+
model_module: full._model_module,
|
|
220
|
+
model_module_version: full._model_module_version,
|
|
221
|
+
state: full
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
const { state, bufferPaths, buffers } = removeBuffers(states);
|
|
225
|
+
control.send({ method: "update_states", states: state, buffer_paths: bufferPaths }, { buffers });
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
return function widget({ esm, css, state = {} } = {}) {
|
|
229
|
+
if (typeof esm !== "string") throw new TypeError("jupyter.widget needs an `esm` module string");
|
|
230
|
+
const initial = { ...state };
|
|
231
|
+
const full = {
|
|
232
|
+
...ANYWIDGET_MODEL,
|
|
233
|
+
_esm: esm,
|
|
234
|
+
...css === void 0 ? {} : { _css: css },
|
|
235
|
+
_anywidget_id: "cdp-kernel.widget",
|
|
236
|
+
...initial
|
|
237
|
+
};
|
|
238
|
+
const { state: wire, bufferPaths, buffers } = removeBuffers(full);
|
|
239
|
+
const comm = commApi.open(WIDGET_TARGET, { state: wire, buffer_paths: bufferPaths }, {
|
|
240
|
+
metadata: { version: WIDGET_PROTOCOL_VERSION },
|
|
241
|
+
buffers
|
|
242
|
+
});
|
|
243
|
+
const instance = new Widget(comm, { ...full }, $display2);
|
|
244
|
+
live.set(comm.id, instance);
|
|
245
|
+
comm.onMsg((msg) => instance._receive(msg));
|
|
246
|
+
comm.onClose(() => {
|
|
247
|
+
live.delete(comm.id);
|
|
248
|
+
});
|
|
249
|
+
return instance;
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// runtime/display.mjs
|
|
254
|
+
var $display = Symbol.for("Jupyter.display");
|
|
255
|
+
var rawToEntity = /* @__PURE__ */ new Map([
|
|
256
|
+
["&", "&"],
|
|
257
|
+
["<", "<"],
|
|
258
|
+
[">", ">"],
|
|
259
|
+
['"', """],
|
|
260
|
+
["'", "'"]
|
|
261
|
+
]);
|
|
262
|
+
var rawRe = new RegExp(`[${[...rawToEntity.keys()].join("")}]`, "g");
|
|
263
|
+
function escapeHTML(str) {
|
|
264
|
+
return str.replaceAll(rawRe, (m) => rawToEntity.get(m) ?? m);
|
|
265
|
+
}
|
|
266
|
+
function isVegaLike(obj) {
|
|
267
|
+
return obj !== null && typeof obj === "object" && "toSpec" in obj;
|
|
268
|
+
}
|
|
269
|
+
function extractVega(obj) {
|
|
270
|
+
const spec = obj.toSpec();
|
|
271
|
+
if (typeof spec !== "object" || spec === null || !("$schema" in spec)) return null;
|
|
272
|
+
let mediaType = "application/vnd.vega.v5+json";
|
|
273
|
+
if (spec.$schema === "https://vega.github.io/schema/vega-lite/v4.json") {
|
|
274
|
+
mediaType = "application/vnd.vegalite.v4+json";
|
|
275
|
+
} else if (spec.$schema === "https://vega.github.io/schema/vega-lite/v5.json") {
|
|
276
|
+
mediaType = "application/vnd.vegalite.v5+json";
|
|
277
|
+
}
|
|
278
|
+
const summary = summarizeChart(spec);
|
|
279
|
+
return summary === void 0 ? { [mediaType]: spec } : { [mediaType]: spec, "text/plain": summary };
|
|
280
|
+
}
|
|
281
|
+
var VL_TYPES = { Q: "quantitative", N: "nominal", O: "ordinal", T: "temporal", G: "geojson" };
|
|
282
|
+
var MAX_CHILDREN = 6;
|
|
283
|
+
function clip(str, max = 60) {
|
|
284
|
+
return str.length > max ? `${str.slice(0, max - 1)}\u2026` : str;
|
|
285
|
+
}
|
|
286
|
+
function formatNumber(n) {
|
|
287
|
+
return Number.isInteger(n) ? String(n) : String(Number(n.toPrecision(4)));
|
|
288
|
+
}
|
|
289
|
+
function titleText(title) {
|
|
290
|
+
const text = typeof title === "object" && title !== null && !Array.isArray(title) ? title.text : title;
|
|
291
|
+
const str = Array.isArray(text) ? text.join(" ") : typeof text === "string" ? text : "";
|
|
292
|
+
return str ? ` "${clip(str, 80)}"` : "";
|
|
293
|
+
}
|
|
294
|
+
function getField(row, field) {
|
|
295
|
+
if (row === null || typeof row !== "object") return void 0;
|
|
296
|
+
if (field in row) return row[field];
|
|
297
|
+
if (field.includes("\\")) return row[field.replace(/\\(.)/g, "$1")];
|
|
298
|
+
return field.split(".").reduce((obj, key2) => obj === null || typeof obj !== "object" ? void 0 : obj[key2], row);
|
|
299
|
+
}
|
|
300
|
+
function fieldStats(rows, field, type) {
|
|
301
|
+
const values = [];
|
|
302
|
+
for (const row of rows) {
|
|
303
|
+
const value = getField(row, field);
|
|
304
|
+
if (value !== void 0 && value !== null && value !== "") values.push(value);
|
|
305
|
+
}
|
|
306
|
+
if (values.length === 0) return "";
|
|
307
|
+
if (type === "quantitative") {
|
|
308
|
+
let min = Infinity;
|
|
309
|
+
let max = -Infinity;
|
|
310
|
+
for (const value of values) {
|
|
311
|
+
const n = Number(value);
|
|
312
|
+
if (!Number.isFinite(n)) continue;
|
|
313
|
+
if (n < min) min = n;
|
|
314
|
+
if (n > max) max = n;
|
|
315
|
+
}
|
|
316
|
+
if (min > max) return "";
|
|
317
|
+
return min === max ? formatNumber(min) : `${formatNumber(min)} to ${formatNumber(max)}`;
|
|
318
|
+
}
|
|
319
|
+
if (type === "temporal") {
|
|
320
|
+
let min;
|
|
321
|
+
let max;
|
|
322
|
+
for (const value of values) {
|
|
323
|
+
const t = value instanceof Date ? value.getTime() : typeof value === "number" ? value : Date.parse(String(value));
|
|
324
|
+
if (!Number.isFinite(t)) continue;
|
|
325
|
+
if (min === void 0 || t < min.t) min = { t, value };
|
|
326
|
+
if (max === void 0 || t > max.t) max = { t, value };
|
|
327
|
+
}
|
|
328
|
+
if (min === void 0) return "";
|
|
329
|
+
const show = ({ value }) => typeof value === "string" ? clip(value, 30) : new Date(value instanceof Date ? value.getTime() : value).toISOString();
|
|
330
|
+
return min.t === max.t ? show(min) : `${show(min)} to ${show(max)}`;
|
|
331
|
+
}
|
|
332
|
+
const distinct = new Set(values.map((value) => typeof value === "object" ? JSON.stringify(value) : String(value)));
|
|
333
|
+
return `${distinct.size} ${distinct.size === 1 ? "value" : "values"}`;
|
|
334
|
+
}
|
|
335
|
+
function encodingSummary(encoding, rows) {
|
|
336
|
+
const parts = [];
|
|
337
|
+
for (const [channel, def] of Object.entries(encoding)) {
|
|
338
|
+
if (channel === "tooltip" || def === null || typeof def !== "object" || Array.isArray(def)) continue;
|
|
339
|
+
if (def.field === void 0 && def.aggregate === void 0) continue;
|
|
340
|
+
let name = typeof def.field === "string" ? def.field : def.field?.repeat ? `repeat ${def.field.repeat}` : "";
|
|
341
|
+
if (def.aggregate !== void 0) name = `${def.aggregate}(${name})`;
|
|
342
|
+
else if (def.timeUnit !== void 0) name = `${typeof def.timeUnit === "string" ? def.timeUnit : "time"}(${name})`;
|
|
343
|
+
const type = VL_TYPES[def.type] ?? def.type;
|
|
344
|
+
const details = [];
|
|
345
|
+
if (typeof type === "string") details.push(type);
|
|
346
|
+
if (rows && typeof def.field === "string" && def.aggregate === void 0) {
|
|
347
|
+
const stats = fieldStats(rows, def.field, type);
|
|
348
|
+
if (stats) details.push(stats);
|
|
349
|
+
}
|
|
350
|
+
parts.push(`${channel}=${clip(name, 40)}${details.length ? ` (${details.join(", ")})` : ""}`);
|
|
351
|
+
}
|
|
352
|
+
return parts;
|
|
353
|
+
}
|
|
354
|
+
function vlRows(data, datasets) {
|
|
355
|
+
if (data === null || typeof data !== "object") return void 0;
|
|
356
|
+
if (Array.isArray(data.values)) return data.values;
|
|
357
|
+
if (typeof data.name === "string" && Array.isArray(datasets?.[data.name])) return datasets[data.name];
|
|
358
|
+
return void 0;
|
|
359
|
+
}
|
|
360
|
+
function vlDataNote(data, rows) {
|
|
361
|
+
if (rows) return `${rows.length} ${rows.length === 1 ? "row" : "rows"}`;
|
|
362
|
+
if (typeof data?.url === "string") return `data from ${clip(data.url)}`;
|
|
363
|
+
return "";
|
|
364
|
+
}
|
|
365
|
+
function fieldList(def) {
|
|
366
|
+
if (Array.isArray(def)) return def.join(", ");
|
|
367
|
+
if (def === null || typeof def !== "object") return "";
|
|
368
|
+
if (typeof def.field === "string") return def.field;
|
|
369
|
+
return Object.values(def).map(fieldList).filter(Boolean).join(", ");
|
|
370
|
+
}
|
|
371
|
+
function summarizeVegaLiteView(spec, label, inherited, datasets, depth, lines) {
|
|
372
|
+
const indent = " ".repeat(depth);
|
|
373
|
+
const data = spec.data ?? inherited.data;
|
|
374
|
+
const rows = vlRows(data, datasets);
|
|
375
|
+
const head = `${indent}${label}`;
|
|
376
|
+
const title = titleText(spec.title);
|
|
377
|
+
const children = spec.layer ?? spec.concat ?? spec.hconcat ?? spec.vconcat;
|
|
378
|
+
if (Array.isArray(children)) {
|
|
379
|
+
const noun = spec.layer ? "layer" : "view";
|
|
380
|
+
const note = [`${children.length} ${children.length === 1 ? noun : `${noun}s`}`, vlDataNote(data, rows)].filter(Boolean);
|
|
381
|
+
lines.push(`${head}${spec.layer ? "layered" : "concatenated"} chart${title}: ${note.join(", ")}`);
|
|
382
|
+
const encoding2 = spec.layer ? { ...inherited.encoding, ...spec.encoding } : {};
|
|
383
|
+
children.slice(0, MAX_CHILDREN).forEach((child, i) => {
|
|
384
|
+
if (child !== null && typeof child === "object") {
|
|
385
|
+
summarizeVegaLiteView(child, `${noun} ${i + 1}: `, { data, encoding: encoding2 }, datasets, depth + 1, lines);
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
if (children.length > MAX_CHILDREN) lines.push(`${indent} \u2026 ${children.length - MAX_CHILDREN} more`);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
if ((spec.facet !== void 0 || spec.repeat !== void 0) && spec.spec !== null && typeof spec.spec === "object") {
|
|
392
|
+
const what = spec.facet !== void 0 ? `faceted by ${fieldList(spec.facet)}` : `repeated over ${fieldList(spec.repeat)}`;
|
|
393
|
+
const note = vlDataNote(data, rows);
|
|
394
|
+
lines.push(`${head}chart${title} ${what}${note ? `, ${note}` : ""}`);
|
|
395
|
+
summarizeVegaLiteView(spec.spec, "each panel: ", { data, encoding: {} }, datasets, depth + 1, lines);
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
const mark = typeof spec.mark === "string" ? spec.mark : spec.mark?.type;
|
|
399
|
+
const encoding = { ...inherited.encoding, ...spec.encoding };
|
|
400
|
+
const parts = encodingSummary(encoding, rows);
|
|
401
|
+
if (spec.data !== void 0 || depth === 0) {
|
|
402
|
+
const note = vlDataNote(data, rows);
|
|
403
|
+
if (note) parts.push(note);
|
|
404
|
+
}
|
|
405
|
+
lines.push(`${head}${typeof mark === "string" ? `${mark} ` : ""}chart${title}${parts.length ? `: ${parts.join(", ")}` : ""}`);
|
|
406
|
+
}
|
|
407
|
+
function vegaMarkTypes(marks, types) {
|
|
408
|
+
if (!Array.isArray(marks)) return types;
|
|
409
|
+
for (const mark of marks) {
|
|
410
|
+
if (typeof mark?.type === "string") types.add(mark.type);
|
|
411
|
+
vegaMarkTypes(mark?.marks, types);
|
|
412
|
+
}
|
|
413
|
+
return types;
|
|
414
|
+
}
|
|
415
|
+
function summarizeVega(spec) {
|
|
416
|
+
const sections = [];
|
|
417
|
+
const marks = [...vegaMarkTypes(spec.marks, /* @__PURE__ */ new Set())];
|
|
418
|
+
if (marks.length) sections.push(`marks ${marks.join(", ")}`);
|
|
419
|
+
const list2 = (items, describe) => {
|
|
420
|
+
const shown = items.slice(0, MAX_CHILDREN).map(describe);
|
|
421
|
+
if (items.length > MAX_CHILDREN) shown.push(`\u2026 ${items.length - MAX_CHILDREN} more`);
|
|
422
|
+
return shown.join(", ");
|
|
423
|
+
};
|
|
424
|
+
const data = Array.isArray(spec.data) ? spec.data.filter((d) => d !== null && typeof d === "object") : [];
|
|
425
|
+
if (data.length) {
|
|
426
|
+
sections.push(`data ${list2(data, (d) => {
|
|
427
|
+
const name = clip(String(d.name ?? "?"), 30);
|
|
428
|
+
if (Array.isArray(d.values)) return `${name} (${d.values.length} ${d.values.length === 1 ? "row" : "rows"})`;
|
|
429
|
+
if (typeof d.url === "string") return `${name} (from ${clip(d.url)})`;
|
|
430
|
+
if (d.source !== void 0) return `${name} (from ${clip(String(d.source), 30)})`;
|
|
431
|
+
return name;
|
|
432
|
+
})}`);
|
|
433
|
+
}
|
|
434
|
+
const scales = Array.isArray(spec.scales) ? spec.scales.filter((s) => s !== null && typeof s === "object") : [];
|
|
435
|
+
if (scales.length) {
|
|
436
|
+
sections.push(`scales ${list2(scales, (s) => `${clip(String(s.name ?? "?"), 30)} (${s.type ?? "linear"})`)}`);
|
|
437
|
+
}
|
|
438
|
+
return `Vega chart${titleText(spec.title)}${sections.length ? `: ${sections.join("; ")}` : ""}`;
|
|
439
|
+
}
|
|
440
|
+
function summarizeChart(spec) {
|
|
441
|
+
try {
|
|
442
|
+
if (typeof spec.$schema === "string" && spec.$schema.includes("/vega-lite/")) {
|
|
443
|
+
const lines = [];
|
|
444
|
+
summarizeVegaLiteView(spec, "Vega-Lite ", { encoding: {} }, spec.datasets, 0, lines);
|
|
445
|
+
return lines.join("\n");
|
|
446
|
+
}
|
|
447
|
+
return summarizeVega(spec);
|
|
448
|
+
} catch {
|
|
449
|
+
return void 0;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
function isDataFrameLike(obj) {
|
|
453
|
+
return obj !== null && typeof obj === "object" && obj.schema !== void 0 && typeof obj.schema === "object" && typeof obj.head === "function" && typeof obj.toRecords === "function";
|
|
454
|
+
}
|
|
455
|
+
function mapPolarsTypeToJSONSchema(colType) {
|
|
456
|
+
const typeMapping = {
|
|
457
|
+
Null: "null",
|
|
458
|
+
Bool: "boolean",
|
|
459
|
+
Int8: "integer",
|
|
460
|
+
Int16: "integer",
|
|
461
|
+
Int32: "integer",
|
|
462
|
+
Int64: "integer",
|
|
463
|
+
UInt8: "integer",
|
|
464
|
+
UInt16: "integer",
|
|
465
|
+
UInt32: "integer",
|
|
466
|
+
UInt64: "integer",
|
|
467
|
+
Float32: "number",
|
|
468
|
+
Float64: "number",
|
|
469
|
+
Date: "string",
|
|
470
|
+
Datetime: "string",
|
|
471
|
+
Utf8: "string",
|
|
472
|
+
Categorical: "string",
|
|
473
|
+
List: "array",
|
|
474
|
+
Struct: "object"
|
|
475
|
+
};
|
|
476
|
+
const dataType = typeof colType?.toJSON === "function" ? colType.toJSON()["DataType"] : void 0;
|
|
477
|
+
return typeMapping[dataType] || "string";
|
|
478
|
+
}
|
|
479
|
+
function extractDataFrame(df) {
|
|
480
|
+
const fields = [];
|
|
481
|
+
for (const [name, colType] of Object.entries(df.schema)) {
|
|
482
|
+
fields.push({ name, type: mapPolarsTypeToJSONSchema(colType) });
|
|
483
|
+
}
|
|
484
|
+
const data = df.head(50).toRecords();
|
|
485
|
+
let html = "<table><thead><tr>";
|
|
486
|
+
for (const field of fields) html += `<th>${escapeHTML(String(field.name))}</th>`;
|
|
487
|
+
html += "</tr></thead><tbody>";
|
|
488
|
+
for (const row of df.head(10).toRecords()) {
|
|
489
|
+
html += "<tr>";
|
|
490
|
+
for (const field of fields) html += `<td>${escapeHTML(String(row[field.name]))}</td>`;
|
|
491
|
+
html += "</tr>";
|
|
492
|
+
}
|
|
493
|
+
html += "</tbody></table>";
|
|
494
|
+
const size = [];
|
|
495
|
+
if (Number.isInteger(df.height)) size.push(`${df.height} ${df.height === 1 ? "row" : "rows"}`);
|
|
496
|
+
size.push(`${fields.length} ${fields.length === 1 ? "column" : "columns"}`);
|
|
497
|
+
const columns = fields.slice(0, 20).map((field) => `${clip(String(field.name), 40)} (${field.type})`);
|
|
498
|
+
if (fields.length > 20) columns.push(`\u2026 ${fields.length - 20} more`);
|
|
499
|
+
return {
|
|
500
|
+
"application/vnd.dataresource+json": { data, schema: { fields } },
|
|
501
|
+
"text/html": html,
|
|
502
|
+
"text/plain": `DataFrame (${size.join(", ")})${columns.length ? `: ${columns.join(", ")}` : ""}`
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
function isCanvasLike(obj) {
|
|
506
|
+
return obj !== null && typeof obj === "object" && "toDataURL" in obj;
|
|
507
|
+
}
|
|
508
|
+
function isJpg(obj) {
|
|
509
|
+
return obj instanceof Uint8Array && obj.length >= 4 && obj[0] === 255 && obj[1] === 216 && obj[obj.length - 2] === 255 && obj[obj.length - 1] === 217;
|
|
510
|
+
}
|
|
511
|
+
var PNG_SIGNATURE = [137, 80, 78, 71, 13, 10, 26, 10];
|
|
512
|
+
function isPng(obj) {
|
|
513
|
+
return obj instanceof Uint8Array && obj.length >= PNG_SIGNATURE.length && PNG_SIGNATURE.every((byte, i) => obj[i] === byte);
|
|
514
|
+
}
|
|
515
|
+
function isSVGElementLike(obj) {
|
|
516
|
+
return obj !== null && typeof obj === "object" && typeof obj.outerHTML === "string" && obj.outerHTML.startsWith("<svg");
|
|
517
|
+
}
|
|
518
|
+
function isHTMLElementLike(obj) {
|
|
519
|
+
return obj !== null && typeof obj === "object" && typeof obj.outerHTML === "string";
|
|
520
|
+
}
|
|
521
|
+
function hasDisplaySymbol(obj) {
|
|
522
|
+
return obj !== null && typeof obj === "object" && typeof obj[$display] === "function";
|
|
523
|
+
}
|
|
524
|
+
function isMediaBundle(obj) {
|
|
525
|
+
return obj !== null && typeof obj === "object" && !Array.isArray(obj);
|
|
526
|
+
}
|
|
527
|
+
function createJupyter(host2) {
|
|
528
|
+
async function format2(obj) {
|
|
529
|
+
return await formatNow(obj);
|
|
530
|
+
}
|
|
531
|
+
function formatNow(obj) {
|
|
532
|
+
if (hasDisplaySymbol(obj)) return obj[$display]();
|
|
533
|
+
if (typeof obj !== "object" || obj === null) return { "text/plain": host2.inspect(obj) };
|
|
534
|
+
if (isCanvasLike(obj)) {
|
|
535
|
+
const [prefix, data] = obj.toDataURL().split(",");
|
|
536
|
+
return { [prefix.split(":")[1].split(";")[0]]: data };
|
|
537
|
+
}
|
|
538
|
+
if (isVegaLike(obj)) {
|
|
539
|
+
const vega = extractVega(obj);
|
|
540
|
+
if (vega) return vega;
|
|
541
|
+
}
|
|
542
|
+
if (isDataFrameLike(obj)) return extractDataFrame(obj);
|
|
543
|
+
if (isJpg(obj)) return { "image/jpeg": host2.base64(obj) };
|
|
544
|
+
if (isPng(obj)) return { "image/png": host2.base64(obj) };
|
|
545
|
+
if (isSVGElementLike(obj)) return { "image/svg+xml": obj.outerHTML };
|
|
546
|
+
if (isHTMLElementLike(obj)) return { "text/html": obj.outerHTML };
|
|
547
|
+
return { "text/plain": host2.inspect(obj) };
|
|
548
|
+
}
|
|
549
|
+
function taggedTemplate(mediatype) {
|
|
550
|
+
return (strings, ...values) => {
|
|
551
|
+
const payload = strings.reduce((acc, string, i) => acc + string + (values[i] !== void 0 ? values[i] : ""), "");
|
|
552
|
+
return { [$display]: () => ({ [mediatype]: payload }) };
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
function image(obj) {
|
|
556
|
+
if (typeof obj === "string") {
|
|
557
|
+
try {
|
|
558
|
+
obj = host2.readFile(obj);
|
|
559
|
+
} catch {
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
if (isJpg(obj)) return { [$display]: () => ({ "image/jpeg": host2.base64(obj) }) };
|
|
563
|
+
if (isPng(obj)) return { [$display]: () => ({ "image/png": host2.base64(obj) }) };
|
|
564
|
+
throw new TypeError(
|
|
565
|
+
"Object is not a valid image or a path to an image. `jupyter.image` supports displaying JPG or PNG images."
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
function broadcast(msgType, content, { metadata = {}, buffers = [] } = {}) {
|
|
569
|
+
host2.send(msgType, content, metadata, buffers);
|
|
570
|
+
}
|
|
571
|
+
async function display(obj, options = { raw: false, update: false }) {
|
|
572
|
+
const bundle = options.raw && isMediaBundle(obj) ? obj : await format2(obj);
|
|
573
|
+
broadcast(options.update ? "update_display_data" : "display_data", {
|
|
574
|
+
data: bundle,
|
|
575
|
+
metadata: {},
|
|
576
|
+
transient: options.display_id ? { display_id: options.display_id } : {}
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
async function broadcastResult(executionCount, result) {
|
|
580
|
+
if (result === void 0) return;
|
|
581
|
+
try {
|
|
582
|
+
broadcast("execute_result", {
|
|
583
|
+
execution_count: executionCount,
|
|
584
|
+
data: await format2(result),
|
|
585
|
+
metadata: {},
|
|
586
|
+
// nbclient crashes on a null `transient`; Deno learned this too.
|
|
587
|
+
transient: {}
|
|
588
|
+
});
|
|
589
|
+
} catch (err) {
|
|
590
|
+
broadcast("error", {
|
|
591
|
+
ename: err instanceof Error ? err.name : "Error",
|
|
592
|
+
evalue: err instanceof Error ? err.message : String(err),
|
|
593
|
+
traceback: err instanceof Error && err.stack ? err.stack.split("\n") : []
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
function confirm(message = "Confirm") {
|
|
598
|
+
const answer2 = host2.input(`${message} [y/N] `, false);
|
|
599
|
+
return answer2 === "Y" || answer2 === "y";
|
|
600
|
+
}
|
|
601
|
+
function prompt(message = "Prompt", defaultValue = "", { password = false } = {}) {
|
|
602
|
+
if (defaultValue != "") message += ` [${defaultValue}]`;
|
|
603
|
+
const answer2 = host2.input(message, password);
|
|
604
|
+
return answer2 === "" ? defaultValue : answer2;
|
|
605
|
+
}
|
|
606
|
+
const comms = createComms((msgType, content, metadata, buffers) => host2.send(msgType, content, metadata, buffers));
|
|
607
|
+
return {
|
|
608
|
+
namespace: {
|
|
609
|
+
broadcast,
|
|
610
|
+
display,
|
|
611
|
+
format: format2,
|
|
612
|
+
md: taggedTemplate("text/markdown"),
|
|
613
|
+
html: taggedTemplate("text/html"),
|
|
614
|
+
svg: taggedTemplate("image/svg+xml"),
|
|
615
|
+
image,
|
|
616
|
+
$display,
|
|
617
|
+
comm: comms.api,
|
|
618
|
+
widget: createWidgetFactory(comms.api, $display)
|
|
619
|
+
},
|
|
620
|
+
broadcastResult,
|
|
621
|
+
formatNow,
|
|
622
|
+
confirm,
|
|
623
|
+
prompt,
|
|
624
|
+
commDispatch: comms.dispatch
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// runtime/evaluator.mjs
|
|
629
|
+
function propertyNames(value) {
|
|
630
|
+
if (value === null || value === void 0) return [];
|
|
631
|
+
const names = /* @__PURE__ */ new Set();
|
|
632
|
+
for (let o = Object(value); o !== null; o = Object.getPrototypeOf(o)) {
|
|
633
|
+
for (const name of Object.getOwnPropertyNames(o)) names.add(name);
|
|
634
|
+
}
|
|
635
|
+
return [...names];
|
|
636
|
+
}
|
|
637
|
+
function createHandler(shim, evaluate = (code) => (0, eval)(code)) {
|
|
638
|
+
const handles = /* @__PURE__ */ new Map();
|
|
639
|
+
let nextHandle = 0;
|
|
640
|
+
const remote = (value) => {
|
|
641
|
+
const objectId = `h${++nextHandle}`;
|
|
642
|
+
handles.set(objectId, value);
|
|
643
|
+
return { type: value === null ? "object" : typeof value, objectId };
|
|
644
|
+
};
|
|
645
|
+
const take = (objectId) => {
|
|
646
|
+
const value = handles.get(objectId);
|
|
647
|
+
handles.delete(objectId);
|
|
648
|
+
return value;
|
|
649
|
+
};
|
|
650
|
+
return async function handle2(request) {
|
|
651
|
+
switch (request.op) {
|
|
652
|
+
case "ping":
|
|
653
|
+
return {};
|
|
654
|
+
case "eval": {
|
|
655
|
+
handles.clear();
|
|
656
|
+
try {
|
|
657
|
+
const box = await evaluate(request.code);
|
|
658
|
+
return { result: box === void 0 ? { type: "undefined" } : remote(box[0]) };
|
|
659
|
+
} catch (err) {
|
|
660
|
+
return {
|
|
661
|
+
exceptionDetails: { text: "Uncaught", lineNumber: 0, columnNumber: 0, exception: remote(err) }
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
case "broadcast":
|
|
666
|
+
await shim.broadcastResult(request.count, take(request.handle));
|
|
667
|
+
return {};
|
|
668
|
+
case "format":
|
|
669
|
+
return { value: await shim.formatJson(request.handle === void 0 ? void 0 : take(request.handle)) };
|
|
670
|
+
case "describe":
|
|
671
|
+
return { value: shim.describeError(take(request.handle)) };
|
|
672
|
+
case "comm":
|
|
673
|
+
try {
|
|
674
|
+
const handled = await shim.commDispatch(request.msgType, request.content, request.metadata, request.buffers);
|
|
675
|
+
return { handled: handled === true };
|
|
676
|
+
} catch (err) {
|
|
677
|
+
return { error: JSON.parse(shim.describeError(err)) };
|
|
678
|
+
}
|
|
679
|
+
case "props": {
|
|
680
|
+
if (typeof shim.resolvePath === "function") {
|
|
681
|
+
const resolved = shim.resolvePath(request.expr);
|
|
682
|
+
return { names: resolved.found && !resolved.accessor ? propertyNames(resolved.value) : [] };
|
|
683
|
+
}
|
|
684
|
+
let value;
|
|
685
|
+
try {
|
|
686
|
+
value = evaluate(`(${request.expr})`);
|
|
687
|
+
} catch {
|
|
688
|
+
return { names: [] };
|
|
689
|
+
}
|
|
690
|
+
return { names: propertyNames(value) };
|
|
691
|
+
}
|
|
692
|
+
case "inspect":
|
|
693
|
+
return { text: shim.inspectPath(request.path, request.detail ?? 0) };
|
|
694
|
+
case "barrier":
|
|
695
|
+
return { value: shim.barrier() };
|
|
696
|
+
default:
|
|
697
|
+
throw new Error(`unknown request ${JSON.stringify(request.op)}`);
|
|
698
|
+
}
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// runtime/format.mjs
|
|
703
|
+
var MAX_ITEMS = 100;
|
|
704
|
+
function quote(s) {
|
|
705
|
+
const q = !s.includes("'") ? "'" : !s.includes('"') ? '"' : !s.includes("`") && !s.includes("${") ? "`" : "'";
|
|
706
|
+
const escaped = s.replaceAll("\\", "\\\\").replaceAll("\n", "\\n").replaceAll(q, `\\${q}`);
|
|
707
|
+
return `${q}${escaped}${q}`;
|
|
708
|
+
}
|
|
709
|
+
function key(k) {
|
|
710
|
+
return typeof k === "symbol" ? `[${k.toString()}]` : /^[A-Za-z_$][\w$]*$/.test(k) ? k : quote(k);
|
|
711
|
+
}
|
|
712
|
+
function className(value) {
|
|
713
|
+
const proto = Object.getPrototypeOf(value);
|
|
714
|
+
if (proto === null) return "[Object: null prototype]";
|
|
715
|
+
const name = proto.constructor?.name;
|
|
716
|
+
return name && name !== "Object" ? name : "";
|
|
717
|
+
}
|
|
718
|
+
function list(open, items, close, more) {
|
|
719
|
+
if (more > 0) items.push(`... ${more} more item${more === 1 ? "" : "s"}`);
|
|
720
|
+
return items.length === 0 ? `${open}${close}` : `${open} ${items.join(", ")} ${close}`;
|
|
721
|
+
}
|
|
722
|
+
function inspect(value, { depth = 2 } = {}) {
|
|
723
|
+
const seen = [];
|
|
724
|
+
const show = (v, level) => {
|
|
725
|
+
switch (typeof v) {
|
|
726
|
+
case "string":
|
|
727
|
+
return quote(v);
|
|
728
|
+
case "bigint":
|
|
729
|
+
return `${v}n`;
|
|
730
|
+
case "symbol":
|
|
731
|
+
return v.toString();
|
|
732
|
+
case "undefined":
|
|
733
|
+
return "undefined";
|
|
734
|
+
case "function": {
|
|
735
|
+
const isClass = /^class\b/.test(Function.prototype.toString.call(v));
|
|
736
|
+
return isClass ? `[class ${v.name || "(anonymous)"}]` : `[Function${v.name ? `: ${v.name}` : " (anonymous)"}]`;
|
|
737
|
+
}
|
|
738
|
+
case "number":
|
|
739
|
+
return Object.is(v, -0) ? "-0" : String(v);
|
|
740
|
+
case "boolean":
|
|
741
|
+
return String(v);
|
|
742
|
+
}
|
|
743
|
+
if (v === null) return "null";
|
|
744
|
+
if (seen.includes(v)) return "[Circular *1]";
|
|
745
|
+
if (v instanceof Date) return Number.isNaN(v.getTime()) ? "Invalid Date" : v.toISOString();
|
|
746
|
+
if (v instanceof RegExp) return String(v);
|
|
747
|
+
if (v instanceof Error) return v.stack ?? `${v.name}: ${v.message}`;
|
|
748
|
+
if (v instanceof Promise) return "Promise { <unknown> }";
|
|
749
|
+
if (level > depth) return Array.isArray(v) ? "[Array]" : `[${className(v) || "Object"}]`;
|
|
750
|
+
seen.push(v);
|
|
751
|
+
try {
|
|
752
|
+
if (Array.isArray(v) || ArrayBuffer.isView(v)) {
|
|
753
|
+
const items2 = Array.from(v).slice(0, MAX_ITEMS).map((x) => show(x, level + 1));
|
|
754
|
+
const prefix = Array.isArray(v) ? "" : `${v.constructor.name}(${v.length}) `;
|
|
755
|
+
return prefix + list("[", items2, "]", v.length - items2.length);
|
|
756
|
+
}
|
|
757
|
+
if (v instanceof Map) {
|
|
758
|
+
const items2 = [...v].slice(0, MAX_ITEMS).map(([k, x]) => `${show(k, level + 1)} => ${show(x, level + 1)}`);
|
|
759
|
+
return `Map(${v.size}) ` + list("{", items2, "}", v.size - items2.length);
|
|
760
|
+
}
|
|
761
|
+
if (v instanceof Set) {
|
|
762
|
+
const items2 = [...v].slice(0, MAX_ITEMS).map((x) => show(x, level + 1));
|
|
763
|
+
return `Set(${v.size}) ` + list("{", items2, "}", v.size - items2.length);
|
|
764
|
+
}
|
|
765
|
+
const keys = Reflect.ownKeys(v).filter((k) => Object.getOwnPropertyDescriptor(v, k)?.enumerable);
|
|
766
|
+
const items = keys.slice(0, MAX_ITEMS).map((k) => {
|
|
767
|
+
const d = Object.getOwnPropertyDescriptor(v, k);
|
|
768
|
+
const shown = d.get || d.set ? `[${d.get ? "Getter" : ""}${d.get && d.set ? "/" : ""}${d.set ? "Setter" : ""}]` : show(d.value, level + 1);
|
|
769
|
+
return `${key(k)}: ${shown}`;
|
|
770
|
+
});
|
|
771
|
+
const name = className(v);
|
|
772
|
+
return (name ? `${name} ` : "") + list("{", items, "}", keys.length - items.length);
|
|
773
|
+
} finally {
|
|
774
|
+
seen.pop();
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
return show(value, 0);
|
|
778
|
+
}
|
|
779
|
+
function format(...args) {
|
|
780
|
+
let out = [];
|
|
781
|
+
let rest = args;
|
|
782
|
+
if (typeof args[0] === "string" && args.length > 1 && args[0].includes("%")) {
|
|
783
|
+
let i = 1;
|
|
784
|
+
const text = args[0].replace(/%[sdifoOjc%]/g, (spec) => {
|
|
785
|
+
if (spec === "%%") return "%";
|
|
786
|
+
if (i >= args.length) return spec;
|
|
787
|
+
const a = args[i++];
|
|
788
|
+
switch (spec) {
|
|
789
|
+
case "%s":
|
|
790
|
+
return typeof a === "string" ? a : inspect(a, { depth: 1 });
|
|
791
|
+
case "%d":
|
|
792
|
+
case "%i":
|
|
793
|
+
return typeof a === "bigint" ? `${a}n` : String(spec === "%i" ? Math.trunc(Number(a)) : Number(a));
|
|
794
|
+
case "%f":
|
|
795
|
+
return String(Number(a));
|
|
796
|
+
case "%j":
|
|
797
|
+
return JSON.stringify(a);
|
|
798
|
+
case "%c":
|
|
799
|
+
return "";
|
|
800
|
+
default:
|
|
801
|
+
return inspect(a, { depth: 4 });
|
|
802
|
+
}
|
|
803
|
+
});
|
|
804
|
+
out = [text];
|
|
805
|
+
rest = args.slice(i);
|
|
806
|
+
}
|
|
807
|
+
for (const a of rest) out.push(typeof a === "string" ? a : inspect(a));
|
|
808
|
+
return out.join(" ");
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// runtime/introspect.mjs
|
|
812
|
+
var PREVIEW_CHARS = 1500;
|
|
813
|
+
var SOURCE_CHARS = 4e3;
|
|
814
|
+
var MAX_PROPERTIES = 40;
|
|
815
|
+
var IDENTIFIER_PATH = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/;
|
|
816
|
+
function resolvePath(path, root = globalThis) {
|
|
817
|
+
if (!IDENTIFIER_PATH.test(path)) return { found: false };
|
|
818
|
+
let value = root;
|
|
819
|
+
for (const name of path.split(".")) {
|
|
820
|
+
if (value === null || value === void 0) return { found: false };
|
|
821
|
+
let descriptor;
|
|
822
|
+
for (let o = Object(value); o !== null && descriptor === void 0; o = Object.getPrototypeOf(o)) {
|
|
823
|
+
descriptor = Object.getOwnPropertyDescriptor(o, name);
|
|
824
|
+
}
|
|
825
|
+
if (descriptor === void 0) return { found: false };
|
|
826
|
+
if (!("value" in descriptor)) return { found: true, accessor: true, name };
|
|
827
|
+
value = descriptor.value;
|
|
828
|
+
}
|
|
829
|
+
return { found: true, value };
|
|
830
|
+
}
|
|
831
|
+
function truncate(text, limit) {
|
|
832
|
+
return text.length > limit ? `${text.slice(0, limit)}\u2026 (${text.length - limit} more characters)` : text;
|
|
833
|
+
}
|
|
834
|
+
function signatureOf(fn) {
|
|
835
|
+
let source;
|
|
836
|
+
try {
|
|
837
|
+
source = Function.prototype.toString.call(fn);
|
|
838
|
+
} catch {
|
|
839
|
+
return `${fn.name || "anonymous"}(\u2026)`;
|
|
840
|
+
}
|
|
841
|
+
if (/^class\b/.test(source)) return `class ${fn.name || "(anonymous)"}`;
|
|
842
|
+
const params = /^[^(]*\(([^)]*)\)/.exec(source)?.[1];
|
|
843
|
+
const native = /\{\s*\[native code\]\s*\}$/.test(source);
|
|
844
|
+
const written = (params ?? "").replace(/\s+/g, " ").replace(/\s*,\s*/g, ", ").trim();
|
|
845
|
+
const args = native ? Array.from({ length: fn.length }, (_, i) => `arg${i}`).join(", ") : written;
|
|
846
|
+
const arrow = !/^(?:async\s+)?function\b/.test(source) && /=>/.test(source.split("{")[0] ?? "");
|
|
847
|
+
const name = fn.name || (arrow ? "(arrow function)" : "anonymous");
|
|
848
|
+
const prefix = /^async\b/.test(source) ? "async " : "";
|
|
849
|
+
return `${prefix}${name}(${args})`;
|
|
850
|
+
}
|
|
851
|
+
function typeOf(value) {
|
|
852
|
+
if (value === null) return "null";
|
|
853
|
+
if (typeof value !== "object" && typeof value !== "function") return typeof value;
|
|
854
|
+
const name = Object.getPrototypeOf(value)?.constructor?.name;
|
|
855
|
+
if (typeof value === "function") return /^class\b/.test(safeSource(value)) ? "class" : "function";
|
|
856
|
+
return name && name !== "Object" ? `object (${name})` : "object";
|
|
857
|
+
}
|
|
858
|
+
function safeSource(fn) {
|
|
859
|
+
try {
|
|
860
|
+
return Function.prototype.toString.call(fn);
|
|
861
|
+
} catch {
|
|
862
|
+
return "";
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
function propertyNames2(value) {
|
|
866
|
+
if (typeof value !== "object" && typeof value !== "function" || value === null) return [];
|
|
867
|
+
try {
|
|
868
|
+
const internal = ["length", "name", "prototype", "arguments", "caller"];
|
|
869
|
+
return Object.getOwnPropertyNames(value).filter((n) => !(typeof value === "function" && internal.includes(n)));
|
|
870
|
+
} catch {
|
|
871
|
+
return [];
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
function describeValue(value, { inspect: inspect2, detail = 0 }) {
|
|
875
|
+
const lines = [`Type: ${typeOf(value)}`];
|
|
876
|
+
if (typeof value === "function") lines.push(`Signature: ${signatureOf(value)}`);
|
|
877
|
+
let preview;
|
|
878
|
+
try {
|
|
879
|
+
preview = inspect2(value);
|
|
880
|
+
} catch (err) {
|
|
881
|
+
preview = `(inspect failed: ${err instanceof Error ? err.message : String(err)})`;
|
|
882
|
+
}
|
|
883
|
+
lines.push(`Value: ${truncate(preview, PREVIEW_CHARS)}`);
|
|
884
|
+
const names = propertyNames2(value);
|
|
885
|
+
if (names.length > 0) {
|
|
886
|
+
const shown = names.slice(0, MAX_PROPERTIES).join(", ");
|
|
887
|
+
lines.push(`Properties: ${shown}${names.length > MAX_PROPERTIES ? `, \u2026 (${names.length - MAX_PROPERTIES} more)` : ""}`);
|
|
888
|
+
}
|
|
889
|
+
if (detail > 0 && typeof value === "function") lines.push(`Source:
|
|
890
|
+
${truncate(safeSource(value), SOURCE_CHARS)}`);
|
|
891
|
+
return lines.join("\n");
|
|
892
|
+
}
|
|
893
|
+
function inspectPath(path, { inspect: inspect2, detail = 0, root = globalThis }) {
|
|
894
|
+
const resolved = resolvePath(path, root);
|
|
895
|
+
if (!resolved.found) return null;
|
|
896
|
+
if (resolved.accessor) {
|
|
897
|
+
return `Type: accessor property
|
|
898
|
+
${resolved.name} has a getter, which isn't called for inspection: it could have side effects.`;
|
|
899
|
+
}
|
|
900
|
+
return describeValue(resolved.value, { inspect: inspect2, detail });
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
// runtime/cdn.mjs
|
|
904
|
+
var DEFAULT_CDN = "https://esm.sh/";
|
|
905
|
+
function resolveSpecifier(specifier, base, cdn2 = DEFAULT_CDN) {
|
|
906
|
+
if (/^(?:https?|data|blob):/.test(specifier)) return specifier;
|
|
907
|
+
if (/^\.{0,2}\//.test(specifier)) return new URL(specifier, base).href;
|
|
908
|
+
if (specifier.startsWith("npm:")) return cdn2 + specifier.slice(4);
|
|
909
|
+
if (specifier.startsWith("jsr:")) return `${cdn2}jsr/${specifier.slice(4).replace(/^\//, "")}`;
|
|
910
|
+
return cdn2 + specifier;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
// runtime/browser-worker.mjs
|
|
914
|
+
function base64(bytes) {
|
|
915
|
+
let binary = "";
|
|
916
|
+
for (let i = 0; i < bytes.length; i += 32768) {
|
|
917
|
+
binary += String.fromCharCode(...bytes.subarray(i, i + 32768));
|
|
918
|
+
}
|
|
919
|
+
return btoa(binary);
|
|
920
|
+
}
|
|
921
|
+
var post = (message) => globalThis.postMessage(message);
|
|
922
|
+
var stream = (name) => (...args) => post({ kind: "stream", name, text: format(...args) + "\n" });
|
|
923
|
+
Object.assign(console, {
|
|
924
|
+
log: stream("stdout"),
|
|
925
|
+
info: stream("stdout"),
|
|
926
|
+
debug: stream("stdout"),
|
|
927
|
+
dir: (value) => post({ kind: "stream", name: "stdout", text: inspect(value, { depth: 4 }) + "\n" }),
|
|
928
|
+
warn: stream("stderr"),
|
|
929
|
+
error: stream("stderr")
|
|
930
|
+
});
|
|
931
|
+
function reportUncaught(kind, err) {
|
|
932
|
+
post({ kind: "stream", name: "stderr", text: `${kind}: ${err instanceof Error ? err.stack ?? err.message : inspect(err)}
|
|
933
|
+
` });
|
|
934
|
+
}
|
|
935
|
+
globalThis.addEventListener("unhandledrejection", (event) => {
|
|
936
|
+
event.preventDefault();
|
|
937
|
+
reportUncaught("Uncaught (in promise)", event.reason);
|
|
938
|
+
});
|
|
939
|
+
globalThis.addEventListener("error", (event) => {
|
|
940
|
+
event.preventDefault();
|
|
941
|
+
reportUncaught("Uncaught", event.error ?? event.message);
|
|
942
|
+
});
|
|
943
|
+
var jupyter = createJupyter({
|
|
944
|
+
inspect: (value) => inspect(value, { depth: 4 }),
|
|
945
|
+
base64,
|
|
946
|
+
readFile() {
|
|
947
|
+
throw new Error("the browser target has no file system to read from; pass the image bytes instead");
|
|
948
|
+
},
|
|
949
|
+
send(msgType, content, metadata, buffers) {
|
|
950
|
+
post({ kind: "iopub", msg_type: msgType, content, metadata, buffers: buffers.map(base64), barrier: 0 });
|
|
951
|
+
},
|
|
952
|
+
// A synchronous prompt would need SharedArrayBuffer and Atomics.wait, so
|
|
953
|
+
// a cross-origin isolated page; until then, as with no stdin.
|
|
954
|
+
input: () => null
|
|
955
|
+
});
|
|
956
|
+
var cdn = DEFAULT_CDN;
|
|
957
|
+
var hostCalls = /* @__PURE__ */ new Map();
|
|
958
|
+
var hostListeners = /* @__PURE__ */ new Set();
|
|
959
|
+
var nextHostId = 0;
|
|
960
|
+
function hostError(error) {
|
|
961
|
+
const err = new Error(String(error?.message ?? "the host request failed"));
|
|
962
|
+
if (typeof error?.name === "string") err.name = error.name;
|
|
963
|
+
if (error?.code !== void 0) err.code = error.code;
|
|
964
|
+
return err;
|
|
965
|
+
}
|
|
966
|
+
var host = {
|
|
967
|
+
/** Resolves with the page's answer; aborting `signal` cancels the call on the page too. */
|
|
968
|
+
request(method, params, { signal, transfer } = {}) {
|
|
969
|
+
if (signal?.aborted) return Promise.reject(signal.reason);
|
|
970
|
+
const id = ++nextHostId;
|
|
971
|
+
return new Promise((resolve, reject) => {
|
|
972
|
+
const onAbort = () => {
|
|
973
|
+
hostCalls.delete(id);
|
|
974
|
+
post({ kind: "host", id, cancel: true });
|
|
975
|
+
reject(signal.reason);
|
|
976
|
+
};
|
|
977
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
978
|
+
const done = () => signal?.removeEventListener("abort", onAbort);
|
|
979
|
+
try {
|
|
980
|
+
globalThis.postMessage({ kind: "host", id, method, params }, transfer ?? []);
|
|
981
|
+
} catch (err) {
|
|
982
|
+
done();
|
|
983
|
+
throw err;
|
|
984
|
+
}
|
|
985
|
+
hostCalls.set(id, { resolve, reject, done });
|
|
986
|
+
});
|
|
987
|
+
},
|
|
988
|
+
/** Calls `listener(event, value)` for each event the page sends; returns a function that stops it. */
|
|
989
|
+
onEvent(listener) {
|
|
990
|
+
hostListeners.add(listener);
|
|
991
|
+
return () => hostListeners.delete(listener);
|
|
992
|
+
}
|
|
993
|
+
};
|
|
994
|
+
function receiveHost(msg) {
|
|
995
|
+
if (msg.id === void 0) {
|
|
996
|
+
for (const listener of hostListeners) {
|
|
997
|
+
try {
|
|
998
|
+
listener(msg.event, msg.value);
|
|
999
|
+
} catch (err) {
|
|
1000
|
+
reportUncaught("Uncaught", err);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
const call = hostCalls.get(msg.id);
|
|
1006
|
+
if (!call) return;
|
|
1007
|
+
hostCalls.delete(msg.id);
|
|
1008
|
+
call.done();
|
|
1009
|
+
if (msg.error !== void 0) call.reject(hostError(msg.error));
|
|
1010
|
+
else call.resolve(msg.result);
|
|
1011
|
+
}
|
|
1012
|
+
async function preload(urls, base) {
|
|
1013
|
+
for (const specifier of Array.isArray(urls) ? urls : []) {
|
|
1014
|
+
try {
|
|
1015
|
+
const mod = await import(new URL(specifier, base).href);
|
|
1016
|
+
if (typeof mod.default === "function") await mod.default({ host, jupyter: jupyter.namespace });
|
|
1017
|
+
} catch (err) {
|
|
1018
|
+
reportUncaught(`Preloading ${specifier} failed`, err);
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
var handle = null;
|
|
1023
|
+
function install({ base, cdn: cdnBase }) {
|
|
1024
|
+
if (typeof cdnBase === "string") cdn = cdnBase.endsWith("/") ? cdnBase : cdnBase + "/";
|
|
1025
|
+
const url = new URL("$cdpk$repl.mjs", base).href;
|
|
1026
|
+
globalThis.__cdpk = {
|
|
1027
|
+
import: (specifier, options) => import(resolveSpecifier(specifier, url, cdn)),
|
|
1028
|
+
meta: { url, resolve: (specifier) => resolveSpecifier(specifier, url, cdn) },
|
|
1029
|
+
// inspect_request (#10): by descriptor, so nothing runs.
|
|
1030
|
+
describeForInspect: (value, detail) => describeValue(value, { inspect: (v) => inspect(v, { depth: 2 }), detail }),
|
|
1031
|
+
inspectPath: (path, detail) => inspectPath(path, { inspect: (v) => inspect(v, { depth: 2 }), detail }),
|
|
1032
|
+
resolvePath,
|
|
1033
|
+
barrier: () => 0,
|
|
1034
|
+
broadcastResult: jupyter.broadcastResult,
|
|
1035
|
+
// execute_request's user_expressions (#340).
|
|
1036
|
+
formatJson: async (value) => JSON.stringify(await jupyter.namespace.format(value)),
|
|
1037
|
+
async commDispatch(msgType, content, metadata, buffers64) {
|
|
1038
|
+
const buffers = buffers64.map((b) => Uint8Array.from(atob(b), (c) => c.charCodeAt(0)));
|
|
1039
|
+
return await jupyter.commDispatch(msgType, content, metadata, buffers);
|
|
1040
|
+
},
|
|
1041
|
+
describeError(value) {
|
|
1042
|
+
if (value instanceof Error) {
|
|
1043
|
+
return JSON.stringify({ name: value.name, message: value.message, stack: value.stack ?? "" });
|
|
1044
|
+
}
|
|
1045
|
+
return JSON.stringify({ name: "Error", message: inspect(value), stack: "" });
|
|
1046
|
+
}
|
|
1047
|
+
};
|
|
1048
|
+
Object.defineProperty(globalThis, "__cdpk", { enumerable: false });
|
|
1049
|
+
globalThis.jupyter = jupyter.namespace;
|
|
1050
|
+
globalThis.prompt = jupyter.prompt;
|
|
1051
|
+
globalThis.confirm = jupyter.confirm;
|
|
1052
|
+
handle = createHandler(globalThis.__cdpk, (code) => (0, eval)(code));
|
|
1053
|
+
}
|
|
1054
|
+
async function answer(req) {
|
|
1055
|
+
if (req.op === "info") {
|
|
1056
|
+
install(req);
|
|
1057
|
+
await preload(req.preload, req.base);
|
|
1058
|
+
return { userAgent: globalThis.navigator?.userAgent ?? "" };
|
|
1059
|
+
}
|
|
1060
|
+
if (handle === null) throw new Error("the driver wasn't sent info first");
|
|
1061
|
+
return await handle(req);
|
|
1062
|
+
}
|
|
1063
|
+
globalThis.addEventListener("message", (event) => {
|
|
1064
|
+
const req = event.data;
|
|
1065
|
+
if (req?.op === "host") return receiveHost(req);
|
|
1066
|
+
answer(req).then(
|
|
1067
|
+
(reply) => post({ kind: "reply", id: req.id, ...reply }),
|
|
1068
|
+
(err) => post({ kind: "reply", id: req.id, failure: String(err?.stack ?? err) })
|
|
1069
|
+
);
|
|
1070
|
+
});
|
|
1071
|
+
//# sourceMappingURL=worker.js.map
|