@marimo-team/islands 0.25.3-dev137 → 0.25.3-dev139
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/dist/{ErrorBoundary-CgZ1IpNU.js → ErrorBoundary-BX9mTNLJ.js} +1 -1
- package/dist/assets/__vite-browser-external-DrmlAsRP.js +1 -0
- package/dist/assets/worker-O2XUgidQ.js +113 -0
- package/dist/{code-visibility-uIcGb1d8.js → code-visibility-gptWgGHp.js} +1 -1
- package/dist/{common-Cn-8v1pu.js → common-mU-2k6Zp.js} +1 -1
- package/dist/{data-grid-overlay-editor-CY38o06k.js → data-grid-overlay-editor-Bdyx_BTg.js} +1 -1
- package/dist/{feedback-button-C8MtB57f.js → feedback-button-BoXM4uir.js} +2 -2
- package/dist/{glide-data-editor-BK5sjGKi.js → glide-data-editor-DaXYMyzk.js} +3 -3
- package/dist/{globals-Dx5-Q1mU.js → globals-Bj4btPVp.js} +1 -1
- package/dist/main.js +29 -28
- package/dist/{number-overlay-editor-woxvu2w0.js → number-overlay-editor-DHfzwLIx.js} +1 -1
- package/dist/{reveal-component-BW15mD8s.js → reveal-component-CurCj3ks.js} +2 -2
- package/package.json +1 -1
- package/src/core/islands/__tests__/bootstrap.test.ts +17 -17
- package/src/core/islands/__tests__/bridge.test.ts +31 -26
- package/src/core/islands/bootstrap.ts +22 -51
- package/src/core/islands/bridge.ts +31 -20
- package/src/core/islands/worker/__tests__/controller.test.ts +0 -1
- package/src/core/islands/worker/controller.ts +0 -4
- package/src/core/islands/worker/worker.tsx +32 -32
- package/src/core/wasm/__tests__/bridge.test.ts +0 -1
- package/src/core/wasm/bridge.ts +0 -13
- package/src/core/wasm/rpc.ts +0 -1
- package/src/core/wasm/worker/bootstrap.ts +1 -15
- package/src/core/wasm/worker/types.ts +1 -6
- package/src/core/wasm/worker/worker.ts +4 -28
- package/src/core/websocket/__tests__/backend.test.ts +41 -13
- package/src/core/websocket/backend.ts +31 -7
- package/src/core/websocket/transports/__tests__/notebook.test.ts +1 -41
- package/src/core/websocket/transports/notebook.ts +0 -31
- package/dist/assets/__vite-browser-external-SaDYcg7x.js +0 -1
- package/dist/assets/worker-CfME3uyi.js +0 -115
- package/src/core/wasm/worker/message-buffer.ts +0 -33
package/dist/main.js
CHANGED
|
@@ -7,7 +7,7 @@ import { C as T, F as E, G as D, I as O, J as k, K as A, L as j, P as M, R as N,
|
|
|
7
7
|
import { a as oe, d as se, i as ce, m as le, n as ue, o as de, p as fe, r as pe, t as me } from "./tooltip-CJ4Rqasp.js";
|
|
8
8
|
import { $ as he, A as ge, At as _e, B as ve, Bt as ye, D as be, Dt as xe, G as Se, H as Ce, Ht as we, It as Te, J as Ee, Jt as De, Kt as Oe, M as ke, Mt as Ae, N as je, Nt as Me, O as Ne, Ot as Pe, P as Fe, Q as Ie, S as Le, Tt as Re, V as ze, Vt as Be, Wt as Ve, X as He, Xt as Ue, Y as We, Yt as Ge, _ as Ke, _n as qe, _t as Je, an as Ye, b as Xe, cn as Ze, ct as Qe, dn as $e, dt as et, en as tt, f as nt, ft as rt, g as it, gn as at, gt as ot, h as st, it as ct, jt as lt, k as ut, kt as dt, ln as ft, m as pt, mn as mt, nn as ht, o as gt, p as _t, pn as vt, pt as yt, qt as bt, rn as xt, rt as St, s as Ct, tn as wt, u as Tt, un as Et, v as Dt, xt as Ot, y as kt, z as At } from "./error-entries-CmFDQ9CA.js";
|
|
9
9
|
import { D as jt, E as Mt, O as Nt, S as Pt, T as Ft, _ as It, a as Lt, c as Rt, d as zt, f as Bt, g as Vt, h as Ht, i as Ut, l as Wt, m as Gt, n as Kt, o as qt, p as Jt, r as Yt, s as Xt, t as Zt, u as Qt, v as $t, w as en, x as tn, y as nn } from "./spec-DiSh_qJC.js";
|
|
10
|
-
import { $t as rn, A as an, At as on, B as sn, Bt as cn, C as ln, Ct as un, D as dn, Dt as fn, E as pn, Et as mn, F as hn, Ft as gn, G as _n, Gt as vn, H as yn, Ht as bn, I as xn, It as Sn, J as Cn, Jt as wn, K as Tn, Kt as En, L as Dn, Lt as On, M as kn, Mt as An, N as jn, Nt as Mn, O as Nn, Ot as Pn, P as Fn, Pt as In, Qt as Ln, R as Rn, Rt as zn, S as Bn, St as Vn, T as Hn, Tt as Un, U as Wn, Ut as Gn, V as Kn, Vt as qn, W as Jn, Wt as Yn, X as Xn, Xt as Zn, Y as Qn, Yt as $n, Zt as er, _ as tr, _t as nr, an as rr, at as ir, b as ar, c as or, cn as sr, ct as cr, d as lr, dn as ur, dt as dr, en as fr, et as pr, f as mr, fn as hr, ft as gr, g as _r, gt as vr, h as yr, hn as br, ht as xr, in as Sr, it as Cr, j as wr, jt as Tr, k as Er, kt as Dr, ln as Or, lt as kr, m as Ar, mn as jr, mt as Mr, nn as Nr, nt as Pr, ot as Fr, p as Ir, pn as Lr, pt as Rr, q as zr, qt as Br, r as Vr, rn as Hr, rt as Ur, sn as Wr, st as Gr, t as Kr, tn as qr, tt as Jr, u as Yr, un as Xr, ut as Zr, v as Qr, vt as $r, w as ei, wt as ti, x as ni, y as ri, yt as ii, z as ai, zt as oi } from "./common-
|
|
10
|
+
import { $t as rn, A as an, At as on, B as sn, Bt as cn, C as ln, Ct as un, D as dn, Dt as fn, E as pn, Et as mn, F as hn, Ft as gn, G as _n, Gt as vn, H as yn, Ht as bn, I as xn, It as Sn, J as Cn, Jt as wn, K as Tn, Kt as En, L as Dn, Lt as On, M as kn, Mt as An, N as jn, Nt as Mn, O as Nn, Ot as Pn, P as Fn, Pt as In, Qt as Ln, R as Rn, Rt as zn, S as Bn, St as Vn, T as Hn, Tt as Un, U as Wn, Ut as Gn, V as Kn, Vt as qn, W as Jn, Wt as Yn, X as Xn, Xt as Zn, Y as Qn, Yt as $n, Zt as er, _ as tr, _t as nr, an as rr, at as ir, b as ar, c as or, cn as sr, ct as cr, d as lr, dn as ur, dt as dr, en as fr, et as pr, f as mr, fn as hr, ft as gr, g as _r, gt as vr, h as yr, hn as br, ht as xr, in as Sr, it as Cr, j as wr, jt as Tr, k as Er, kt as Dr, ln as Or, lt as kr, m as Ar, mn as jr, mt as Mr, nn as Nr, nt as Pr, ot as Fr, p as Ir, pn as Lr, pt as Rr, q as zr, qt as Br, r as Vr, rn as Hr, rt as Ur, sn as Wr, st as Gr, t as Kr, tn as qr, tt as Jr, u as Yr, un as Xr, ut as Zr, v as Qr, vt as $r, w as ei, wt as ti, x as ni, y as ri, yt as ii, z as ai, zt as oi } from "./common-mU-2k6Zp.js";
|
|
11
11
|
import { c as si, i as ci, n as li, o as ui, t as di } from "./useLifecycle-B5BX921H.js";
|
|
12
12
|
import { t as fi } from "./check-SpOMoCLP.js";
|
|
13
13
|
import { A as pi, C as mi, D as hi, E as gi, M as _i, O as vi, S as yi, T as bi, a as xi, b as Si, c as Ci, i as wi, l as Ti, n as Ei, o as Di, r as Oi, s as ki, t as Ai, w as ji, x as Mi } from "./select-CkF_GBxO.js";
|
|
@@ -15,8 +15,8 @@ import { B as Ni, C as Pi, J as Fi, Ot as Ii, S as Li, W as Ri, X as zi, Y as Bi
|
|
|
15
15
|
import { C as fa, _ as pa, a as ma, b as ha, c as ga, f as _a, h as va, m as ya, p as ba, s as xa, u as Sa, x as Ca, y as wa } from "./toDate-DGvRHwTk.js";
|
|
16
16
|
import { a as Ta, c as Ea, d as Da, f as Oa, i as ka, l as Aa, n as ja, o as Ma, r as Na, s as Pa, t as Fa } from "./process-output-Bw-vzyoy.js";
|
|
17
17
|
import { a as Ia, c as La, d as Ra, i as za, l as Ba, r as Va, u as Ha } from "./glide-utils-Dz_F4pAY.js";
|
|
18
|
-
import { n as Ua, t as Wa } from "./ErrorBoundary-
|
|
19
|
-
import { n as Ga, t as Ka } from "./globals-
|
|
18
|
+
import { n as Ua, t as Wa } from "./ErrorBoundary-BX9mTNLJ.js";
|
|
19
|
+
import { n as Ga, t as Ka } from "./globals-Bj4btPVp.js";
|
|
20
20
|
import { t as qa } from "./react-dom-DUmH0GXv.js";
|
|
21
21
|
import { t as Ja } from "./jsx-runtime-3BD1kT0s.js";
|
|
22
22
|
import { B as Ya, C as H, Ct as Xa, D as Za, Dt as Qa, E as $a, Et as eo, F as U, G as to, H as no, I as ro, L as io, M as W, N as ao, O as oo, P as so, Q as co, R as lo, S as G, St as uo, Tt as fo, U as po, W as mo, Y as ho, Z as go, _ as _o, _t as vo, a as yo, b as bo, bt as xo, c as So, d as Co, f as wo, g as To, h as Eo, i as Do, j as K, k as Oo, l as ko, m as Ao, n as jo, o as Mo, p as No, r as Po, s as Fo, u as Io, ut as Lo, v as Ro, w as zo, wt as Bo, x as Vo, xt as Ho, y as Uo, yt as Wo } from "./use-restore-focus-CmGwRNId.js";
|
|
@@ -39,7 +39,7 @@ import { t as Ps } from "./useAsyncData-BmVgnMP5.js";
|
|
|
39
39
|
import { i as Fs, n as Is, r as Ls } from "./formats-CCxaLPNs.js";
|
|
40
40
|
import { D as Rs, O as zs } from "./vega-loader.browser-B9Pz0EGP.js";
|
|
41
41
|
import { a as Bs, n as Vs } from "./loader-DOVB0Syl.js";
|
|
42
|
-
import { c as Hs, d as Us, i as Ws, l as Gs, o as Ks, s as qs, t as Js, u as Ys } from "./code-visibility-
|
|
42
|
+
import { c as Hs, d as Us, i as Ws, l as Gs, o as Ks, s as qs, t as Js, u as Ys } from "./code-visibility-gptWgGHp.js";
|
|
43
43
|
import { t as Xs } from "./useDeepCompareMemoize-Ch_AeGu6.js";
|
|
44
44
|
import { t as Zs } from "./esm-D2gTsXEV.js";
|
|
45
45
|
//#region ../node_modules/.pnpm/iconify-icon@2.3.0/node_modules/iconify-icon/dist/iconify-icon.mjs
|
|
@@ -10635,7 +10635,7 @@ function WC(e, t) {
|
|
|
10635
10635
|
}
|
|
10636
10636
|
//#endregion
|
|
10637
10637
|
//#region src/plugins/impl/DataEditorPlugin.tsx
|
|
10638
|
-
var GC = J.lazy(() => import("./glide-data-editor-
|
|
10638
|
+
var GC = J.lazy(() => import("./glide-data-editor-DaXYMyzk.js").then((e) => e.t)), KC = DS("marimo-data-editor", { cssStyles: [XS] }).withData(W({
|
|
10639
10639
|
initialValue: W({ edits: G(W({
|
|
10640
10640
|
rowIdx: K(),
|
|
10641
10641
|
columnId: U(),
|
|
@@ -30407,7 +30407,7 @@ function WR(e) {
|
|
|
30407
30407
|
}
|
|
30408
30408
|
//#endregion
|
|
30409
30409
|
//#region src/components/editor/renderers/slides-layout/slides-layout.tsx
|
|
30410
|
-
var GR = J.lazy(() => import("./reveal-component-
|
|
30410
|
+
var GR = J.lazy(() => import("./reveal-component-CurCj3ks.js")), KR = (e) => {
|
|
30411
30411
|
let t = (0, X.c)(33), { layout: n, setLayout: r, cells: i, mode: a } = e, o = is(pa), s = a === "read" || o, c = is(Ke) > 1, [l, u] = (0, J.useState)(null), d;
|
|
30412
30412
|
t[0] !== i || t[1] !== n ? (d = HP(i, n), t[0] = i, t[1] = n, t[2] = d) : d = t[2];
|
|
30413
30413
|
let { slideCells: f, skippedIds: p, noOutputIds: m, slideTypes: h, startCellIndex: g } = d, _;
|
|
@@ -32115,7 +32115,7 @@ async function RB(e) {
|
|
|
32115
32115
|
LB();
|
|
32116
32116
|
for (let e of r) e.style.removeProperty("opacity");
|
|
32117
32117
|
}
|
|
32118
|
-
}), r.
|
|
32118
|
+
}), r.consumeNotifications((e, n) => {
|
|
32119
32119
|
zB(e, a, t, n);
|
|
32120
32120
|
}), document.addEventListener(Ta.TYPE, () => {
|
|
32121
32121
|
t.set(Us, !0);
|
|
@@ -32123,8 +32123,7 @@ async function RB(e) {
|
|
|
32123
32123
|
}
|
|
32124
32124
|
function zB(e, t, n, r) {
|
|
32125
32125
|
try {
|
|
32126
|
-
|
|
32127
|
-
switch (c.debug("Islands received message:", i.op), i.op) {
|
|
32126
|
+
switch (c.debug("Islands received message:", e.op), e.op) {
|
|
32128
32127
|
case "banner":
|
|
32129
32128
|
case "missing-package-alert":
|
|
32130
32129
|
case "environment-operation":
|
|
@@ -32163,7 +32162,7 @@ function zB(e, t, n, r) {
|
|
|
32163
32162
|
});
|
|
32164
32163
|
return;
|
|
32165
32164
|
case "kernel-ready":
|
|
32166
|
-
tB(
|
|
32165
|
+
tB(e, {
|
|
32167
32166
|
autoInstantiate: !0,
|
|
32168
32167
|
setCells: t.setCells,
|
|
32169
32168
|
setLayoutData: a.NOOP,
|
|
@@ -32174,43 +32173,43 @@ function zB(e, t, n, r) {
|
|
|
32174
32173
|
}), window.customElements?.get(bu.ISLAND) || w_(bu.ISLAND, NB);
|
|
32175
32174
|
return;
|
|
32176
32175
|
case "send-ui-element-message":
|
|
32177
|
-
y_.broadcastMessage(
|
|
32176
|
+
y_.broadcastMessage(e.ui_element, e.message, M(e));
|
|
32178
32177
|
return;
|
|
32179
32178
|
case "remove-ui-elements":
|
|
32180
|
-
nB(
|
|
32179
|
+
nB(e);
|
|
32181
32180
|
return;
|
|
32182
32181
|
case "function-call-result":
|
|
32183
|
-
b_.resolve(
|
|
32182
|
+
b_.resolve(e.function_call_id, e);
|
|
32184
32183
|
return;
|
|
32185
32184
|
case "cell-op":
|
|
32186
|
-
rB(
|
|
32185
|
+
rB(e, t.handleCellMessage);
|
|
32187
32186
|
return;
|
|
32188
32187
|
case "alert":
|
|
32189
32188
|
x({
|
|
32190
|
-
title:
|
|
32191
|
-
description: E({ html:
|
|
32192
|
-
variant:
|
|
32189
|
+
title: e.title,
|
|
32190
|
+
description: E({ html: e.description }),
|
|
32191
|
+
variant: e.variant
|
|
32193
32192
|
});
|
|
32194
32193
|
return;
|
|
32195
32194
|
case "query-params-append":
|
|
32196
|
-
iB.append(
|
|
32195
|
+
iB.append(e);
|
|
32197
32196
|
return;
|
|
32198
32197
|
case "query-params-set":
|
|
32199
|
-
iB.set(
|
|
32198
|
+
iB.set(e);
|
|
32200
32199
|
return;
|
|
32201
32200
|
case "query-params-delete":
|
|
32202
|
-
iB.delete(
|
|
32201
|
+
iB.delete(e);
|
|
32203
32202
|
return;
|
|
32204
32203
|
case "query-params-clear":
|
|
32205
32204
|
iB.clear();
|
|
32206
32205
|
return;
|
|
32207
32206
|
case "model-lifecycle":
|
|
32208
|
-
qg(Kg,
|
|
32207
|
+
qg(Kg, e);
|
|
32209
32208
|
return;
|
|
32210
32209
|
case "consumer-capabilities":
|
|
32211
32210
|
case "execution": return;
|
|
32212
32211
|
default:
|
|
32213
|
-
mi(
|
|
32212
|
+
mi(e);
|
|
32214
32213
|
return;
|
|
32215
32214
|
}
|
|
32216
32215
|
} catch (e) {
|
|
@@ -32445,7 +32444,7 @@ function QB(e, t) {
|
|
|
32445
32444
|
}
|
|
32446
32445
|
//#endregion
|
|
32447
32446
|
//#region src/core/islands/worker/worker.tsx?worker&url
|
|
32448
|
-
var $B = "/assets/worker-
|
|
32447
|
+
var $B = "/assets/worker-O2XUgidQ.js", eV = class {
|
|
32449
32448
|
url;
|
|
32450
32449
|
name;
|
|
32451
32450
|
constructor(e = {}) {
|
|
@@ -32465,7 +32464,7 @@ function tV(e) {
|
|
|
32465
32464
|
//#region src/core/islands/bridge.ts
|
|
32466
32465
|
var nV = class {
|
|
32467
32466
|
rpc;
|
|
32468
|
-
|
|
32467
|
+
notificationConsumer;
|
|
32469
32468
|
store;
|
|
32470
32469
|
root;
|
|
32471
32470
|
session;
|
|
@@ -32491,8 +32490,10 @@ var nV = class {
|
|
|
32491
32490
|
this.store.set(Hs, !0), this.initialized.resolve();
|
|
32492
32491
|
}), this.rpc.addMessageListener("initializedError", ({ error: e }) => {
|
|
32493
32492
|
c.error("Islands initialization error:", e), this.store.set(Hs, e), this.initialized.reject(Error(e));
|
|
32494
|
-
}), this.rpc.addMessageListener("
|
|
32495
|
-
this.activeSessionGenerations.has(
|
|
32493
|
+
}), this.rpc.addMessageListener("notebookEvent", ({ event: e, sessionGeneration: t }) => {
|
|
32494
|
+
if (!this.activeSessionGenerations.has(t)) return;
|
|
32495
|
+
let n = Ue(e);
|
|
32496
|
+
n.event === "marimo" && n.data.marimo && this.notificationConsumer?.(n.data.marimo, t);
|
|
32496
32497
|
});
|
|
32497
32498
|
}
|
|
32498
32499
|
async initializeApps() {
|
|
@@ -32545,8 +32546,8 @@ var nV = class {
|
|
|
32545
32546
|
async startSession(e) {
|
|
32546
32547
|
await this.rpc.proxy.request.startSession(e);
|
|
32547
32548
|
}
|
|
32548
|
-
|
|
32549
|
-
this.
|
|
32549
|
+
consumeNotifications(e) {
|
|
32550
|
+
this.notificationConsumer = e;
|
|
32550
32551
|
}
|
|
32551
32552
|
sendComponentValues = async (e) => (await this.putControlRequest({
|
|
32552
32553
|
type: "update-ui-element",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as e } from "./rolldown-runtime-Cb76FRpK.js";
|
|
2
2
|
import { t } from "./react-sHtZdjeP.js";
|
|
3
|
-
import { a as n } from "./glide-data-editor-
|
|
3
|
+
import { a as n } from "./glide-data-editor-DaXYMyzk.js";
|
|
4
4
|
//#region ../node_modules/.pnpm/@glideapps+glide-data-grid@6.0.4-alpha24_lodash@4.17.21_marked@15.0.12_react-dom@19.3.0_27cffe7f1bc30287d59ac27db3240c5b/node_modules/@glideapps/glide-data-grid/dist/esm/internal/data-grid-overlay-editor/private/number-overlay-editor-style.js
|
|
5
5
|
var r = /* @__PURE__ */ e(t()), i = /*#__PURE__*/ n("div")({
|
|
6
6
|
name: "NumberOverlayEditorStyle",
|
|
@@ -4,14 +4,14 @@ import { t as o } from "./react-sHtZdjeP.js";
|
|
|
4
4
|
import { t as s } from "./compiler-runtime-CldRdSsv.js";
|
|
5
5
|
import { m as c, t as l } from "./tooltip-CJ4Rqasp.js";
|
|
6
6
|
import { k as u } from "./error-entries-CmFDQ9CA.js";
|
|
7
|
-
import { $ as d, Q as f, Z as p, an as m, i as h, l as g, ln as _, n as v, on as y, r as b, t as x, u as S } from "./common-
|
|
7
|
+
import { $ as d, Q as f, Z as p, an as m, i as h, l as g, ln as _, n as v, on as y, r as b, t as x, u as S } from "./common-mU-2k6Zp.js";
|
|
8
8
|
import { M as C } from "./select-CkF_GBxO.js";
|
|
9
9
|
import { J as ee } from "./dropdown-menu-GWcGCcxE.js";
|
|
10
10
|
import { _ as w } from "./toDate-DGvRHwTk.js";
|
|
11
11
|
import { t as T } from "./jsx-runtime-3BD1kT0s.js";
|
|
12
12
|
import { q as E } from "./use-restore-focus-CmGwRNId.js";
|
|
13
13
|
import { A as D, C as O, b as k } from "./useTheme-Bq9pi_vz.js";
|
|
14
|
-
import { a as A, n as te, t as ne } from "./code-visibility-
|
|
14
|
+
import { a as A, n as te, t as ne } from "./code-visibility-gptWgGHp.js";
|
|
15
15
|
/* empty css */
|
|
16
16
|
var j = c("sticky-note", [["path", {
|
|
17
17
|
d: "M21 9a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 15 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2z",
|
package/package.json
CHANGED
|
@@ -6,17 +6,17 @@ import { RuntimeState } from "@/core/kernel/RuntimeState";
|
|
|
6
6
|
import { initializeIslands } from "../bootstrap";
|
|
7
7
|
import type { IslandsPyodideBridge } from "../bridge";
|
|
8
8
|
import { islandsHydratedAtom, islandsPendingInitialRunsAtom } from "../state";
|
|
9
|
-
import type {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
9
|
+
import type { NotificationMessage } from "@/core/kernel/messages";
|
|
10
|
+
|
|
11
|
+
type Consumer = (
|
|
12
|
+
notification: NotificationMessage,
|
|
13
|
+
sessionGeneration: number,
|
|
14
|
+
) => void;
|
|
15
|
+
|
|
16
|
+
const completedRun = {
|
|
17
|
+
op: "completed-run",
|
|
18
|
+
run_id: null,
|
|
19
|
+
} as NotificationMessage;
|
|
20
20
|
|
|
21
21
|
describe("initializeIslands", () => {
|
|
22
22
|
afterEach(vi.restoreAllMocks);
|
|
@@ -26,9 +26,9 @@ describe("initializeIslands", () => {
|
|
|
26
26
|
root.innerHTML =
|
|
27
27
|
'<marimo-island data-app-id="app-1" data-reactive="true"></marimo-island>';
|
|
28
28
|
|
|
29
|
-
let consumeMessage:
|
|
29
|
+
let consumeMessage: Consumer | undefined;
|
|
30
30
|
const bridge = {
|
|
31
|
-
|
|
31
|
+
consumeNotifications: (consumer: Consumer) => {
|
|
32
32
|
consumeMessage = consumer;
|
|
33
33
|
},
|
|
34
34
|
sendComponentValues: vi.fn(),
|
|
@@ -48,14 +48,14 @@ describe("initializeIslands", () => {
|
|
|
48
48
|
expect(store.get(islandsHydratedAtom)).toBe(false);
|
|
49
49
|
store.set(islandsPendingInitialRunsAtom, new Set([1, 2]));
|
|
50
50
|
|
|
51
|
-
consumeMessage?.(completedRun
|
|
51
|
+
consumeMessage?.(completedRun, 1);
|
|
52
52
|
expect(store.get(islandsHydratedAtom)).toBe(false);
|
|
53
53
|
|
|
54
|
-
consumeMessage?.(completedRun
|
|
55
|
-
consumeMessage?.(completedRun
|
|
54
|
+
consumeMessage?.(completedRun, 1);
|
|
55
|
+
consumeMessage?.(completedRun, 0);
|
|
56
56
|
expect(store.get(islandsHydratedAtom)).toBe(false);
|
|
57
57
|
|
|
58
|
-
consumeMessage?.(completedRun
|
|
58
|
+
consumeMessage?.(completedRun, 2);
|
|
59
59
|
expect(store.get(islandsHydratedAtom)).toBe(true);
|
|
60
60
|
});
|
|
61
61
|
});
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
} from "@/__tests__/branded";
|
|
11
11
|
import { notebookAtom } from "@/core/cells/cells";
|
|
12
12
|
import { islandsPendingInitialRunsAtom } from "@/core/islands/state";
|
|
13
|
-
import type { IslandsKernelMessage } from "../worker/worker";
|
|
14
13
|
|
|
15
14
|
type Base64String = components["schemas"]["Base64String"];
|
|
16
15
|
interface TestIslandApp {
|
|
@@ -89,9 +88,6 @@ vi.mock("@/core/wasm/rpc", () => ({
|
|
|
89
88
|
startSession: mockStartSessionRequest,
|
|
90
89
|
stopSession: mockStopSessionRequest,
|
|
91
90
|
},
|
|
92
|
-
send: {
|
|
93
|
-
consumerReady: vi.fn(),
|
|
94
|
-
},
|
|
95
91
|
},
|
|
96
92
|
addMessageListener: vi.fn(
|
|
97
93
|
(name: string, listener: (payload: never) => void) => {
|
|
@@ -177,17 +173,22 @@ describe("IslandsPyodideBridge", () => {
|
|
|
177
173
|
});
|
|
178
174
|
}
|
|
179
175
|
|
|
180
|
-
function
|
|
181
|
-
const listener = mockMessageListeners.get("
|
|
176
|
+
function sendNotebookEvent(sessionGeneration: number, frame: unknown) {
|
|
177
|
+
const listener = mockMessageListeners.get("notebookEvent");
|
|
182
178
|
if (!listener) {
|
|
183
|
-
throw new Error("Missing
|
|
179
|
+
throw new Error("Missing notebook event listener");
|
|
184
180
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
181
|
+
listener({ event: JSON.stringify(frame), sessionGeneration } as never);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** Send a notification and return the call the consumer should receive. */
|
|
185
|
+
function sendKernelMessage(sessionGeneration: number) {
|
|
186
|
+
const notification = { op: "interrupted" };
|
|
187
|
+
sendNotebookEvent(sessionGeneration, {
|
|
188
|
+
event: "marimo",
|
|
189
|
+
data: { marimo: notification },
|
|
190
|
+
});
|
|
191
|
+
return [notification, sessionGeneration];
|
|
191
192
|
}
|
|
192
193
|
|
|
193
194
|
async function initializeSingleApp() {
|
|
@@ -300,7 +301,7 @@ describe("IslandsPyodideBridge", () => {
|
|
|
300
301
|
describe("app lifecycle", () => {
|
|
301
302
|
it("ignores messages after a session yields ownership", async () => {
|
|
302
303
|
const consumeMessage = vi.fn();
|
|
303
|
-
bridge.
|
|
304
|
+
bridge.consumeNotifications(consumeMessage);
|
|
304
305
|
mockSingleApp();
|
|
305
306
|
await bridge.initializeApps();
|
|
306
307
|
|
|
@@ -319,10 +320,7 @@ describe("IslandsPyodideBridge", () => {
|
|
|
319
320
|
sendKernelMessage(1);
|
|
320
321
|
const currentMessage = sendKernelMessage(2);
|
|
321
322
|
|
|
322
|
-
expect(consumeMessage.mock.calls).toEqual([
|
|
323
|
-
[firstMessage],
|
|
324
|
-
[currentMessage],
|
|
325
|
-
]);
|
|
323
|
+
expect(consumeMessage.mock.calls).toEqual([firstMessage, currentMessage]);
|
|
326
324
|
|
|
327
325
|
finishReplacement();
|
|
328
326
|
await replacement;
|
|
@@ -330,7 +328,7 @@ describe("IslandsPyodideBridge", () => {
|
|
|
330
328
|
|
|
331
329
|
it("restores message ownership when replacement fails", async () => {
|
|
332
330
|
const consumeMessage = vi.fn();
|
|
333
|
-
bridge.
|
|
331
|
+
bridge.consumeNotifications(consumeMessage);
|
|
334
332
|
mockSingleApp();
|
|
335
333
|
await bridge.initializeApps();
|
|
336
334
|
mockReplaceSessionRequest.mockRejectedValueOnce(
|
|
@@ -344,12 +342,12 @@ describe("IslandsPyodideBridge", () => {
|
|
|
344
342
|
const previousMessage = sendKernelMessage(1);
|
|
345
343
|
sendKernelMessage(2);
|
|
346
344
|
|
|
347
|
-
expect(consumeMessage.mock.calls).toEqual([
|
|
345
|
+
expect(consumeMessage.mock.calls).toEqual([previousMessage]);
|
|
348
346
|
});
|
|
349
347
|
|
|
350
348
|
it("ignores messages while their session is stopping", async () => {
|
|
351
349
|
const consumeMessage = vi.fn();
|
|
352
|
-
bridge.
|
|
350
|
+
bridge.consumeNotifications(consumeMessage);
|
|
353
351
|
mockSingleApp();
|
|
354
352
|
await bridge.initializeApps();
|
|
355
353
|
let finishStop!: () => void;
|
|
@@ -373,7 +371,7 @@ describe("IslandsPyodideBridge", () => {
|
|
|
373
371
|
|
|
374
372
|
it("forwards messages from every app in a multi-app document", async () => {
|
|
375
373
|
const consumeMessage = vi.fn();
|
|
376
|
-
bridge.
|
|
374
|
+
bridge.consumeNotifications(consumeMessage);
|
|
377
375
|
mockParseMarimoIslandApps.mockReturnValue([app(), app("app-2")]);
|
|
378
376
|
mockCreateMarimoFile
|
|
379
377
|
.mockReturnValueOnce("generated app 1")
|
|
@@ -385,10 +383,17 @@ describe("IslandsPyodideBridge", () => {
|
|
|
385
383
|
const secondMessage = sendKernelMessage(2);
|
|
386
384
|
sendKernelMessage(3);
|
|
387
385
|
|
|
388
|
-
expect(consumeMessage.mock.calls).toEqual([
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
386
|
+
expect(consumeMessage.mock.calls).toEqual([firstMessage, secondMessage]);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it("delivers only the notebook stream's marimo notifications", async () => {
|
|
390
|
+
const consumeMessage = vi.fn();
|
|
391
|
+
bridge.consumeNotifications(consumeMessage);
|
|
392
|
+
await initializeSingleApp();
|
|
393
|
+
sendNotebookEvent(1, { event: "ready", id: "3", data: {} });
|
|
394
|
+
const notification = sendKernelMessage(1);
|
|
395
|
+
|
|
396
|
+
expect(consumeMessage.mock.calls).toEqual([notification]);
|
|
392
397
|
});
|
|
393
398
|
|
|
394
399
|
it("holds controls until the first app session is ready", async () => {
|
|
@@ -9,11 +9,7 @@ import {
|
|
|
9
9
|
} from "@/plugins/impl/anywidget/registry";
|
|
10
10
|
import { initializePlugins } from "@/plugins/plugins";
|
|
11
11
|
import { Functions } from "@/utils/functions";
|
|
12
|
-
import {
|
|
13
|
-
safeExtractSetUIElementMessageBuffers,
|
|
14
|
-
type JsonString,
|
|
15
|
-
} from "@/utils/json/base64";
|
|
16
|
-
import { jsonParseWithSpecialChar } from "@/utils/json/json-parser";
|
|
12
|
+
import { safeExtractSetUIElementMessageBuffers } from "@/utils/json/base64";
|
|
17
13
|
import { Logger } from "@/utils/Logger";
|
|
18
14
|
import { logNever } from "@/utils/assertNever";
|
|
19
15
|
import {
|
|
@@ -30,10 +26,7 @@ import {
|
|
|
30
26
|
handleKernelReady,
|
|
31
27
|
handleRemoveUIElements,
|
|
32
28
|
} from "../kernel/handlers";
|
|
33
|
-
import type {
|
|
34
|
-
NotificationMessage,
|
|
35
|
-
NotificationMessageType,
|
|
36
|
-
} from "../kernel/messages";
|
|
29
|
+
import type { NotificationMessage } from "../kernel/messages";
|
|
37
30
|
import { queryParamHandlers } from "../kernel/queryParamHandlers";
|
|
38
31
|
import { RuntimeState } from "../kernel/RuntimeState";
|
|
39
32
|
import { initialModeAtom } from "../mode";
|
|
@@ -126,19 +119,9 @@ export async function initializeIslands(
|
|
|
126
119
|
}
|
|
127
120
|
});
|
|
128
121
|
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
// as NotificationPayload (just {data}), but the actual wire format
|
|
133
|
-
// includes the outer op too.
|
|
134
|
-
// Worker metadata identifies the session that emitted the message.
|
|
135
|
-
bridge.consumeMessages(({ message, sessionGeneration }) => {
|
|
136
|
-
handleMessage(
|
|
137
|
-
message as unknown as JsonString<IslandsNotificationMessage>,
|
|
138
|
-
actions,
|
|
139
|
-
store,
|
|
140
|
-
sessionGeneration,
|
|
141
|
-
);
|
|
122
|
+
// Each notification names the session that sent it.
|
|
123
|
+
bridge.consumeNotifications((notification, sessionGeneration) => {
|
|
124
|
+
handleNotification(notification, actions, store, sessionGeneration);
|
|
142
125
|
});
|
|
143
126
|
|
|
144
127
|
// Track first user interaction before initialization completes
|
|
@@ -154,27 +137,15 @@ export async function initializeIslands(
|
|
|
154
137
|
RuntimeState.INSTANCE.start(bridge.sendComponentValues);
|
|
155
138
|
}
|
|
156
139
|
|
|
157
|
-
|
|
158
|
-
[K in NotificationMessageType]: {
|
|
159
|
-
data: Extract<NotificationMessage, { op: K }>;
|
|
160
|
-
op: K;
|
|
161
|
-
};
|
|
162
|
-
}[NotificationMessageType];
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Handles a single message from the kernel.
|
|
166
|
-
*
|
|
167
|
-
* Wire format from Python: {"op": "<name>", "data": {"op": "<name>", ...}}
|
|
168
|
-
*/
|
|
140
|
+
/** Handles a single notification from the kernel. */
|
|
169
141
|
// oxlint-disable-next-line marimo/prefer-object-params
|
|
170
|
-
function
|
|
171
|
-
|
|
142
|
+
function handleNotification(
|
|
143
|
+
msg: NotificationMessage,
|
|
172
144
|
actions: NotebookActions,
|
|
173
145
|
store: Store,
|
|
174
146
|
sessionGeneration: number,
|
|
175
147
|
): void {
|
|
176
148
|
try {
|
|
177
|
-
const msg = jsonParseWithSpecialChar(message);
|
|
178
149
|
Logger.debug("Islands received message:", msg.op);
|
|
179
150
|
|
|
180
151
|
switch (msg.op) {
|
|
@@ -223,7 +194,7 @@ function handleMessage(
|
|
|
223
194
|
return;
|
|
224
195
|
|
|
225
196
|
case "kernel-ready":
|
|
226
|
-
handleKernelReady(msg
|
|
197
|
+
handleKernelReady(msg, {
|
|
227
198
|
autoInstantiate: true,
|
|
228
199
|
setCells: actions.setCells,
|
|
229
200
|
setLayoutData: Functions.NOOP,
|
|
@@ -239,47 +210,47 @@ function handleMessage(
|
|
|
239
210
|
|
|
240
211
|
case "send-ui-element-message":
|
|
241
212
|
UI_ELEMENT_REGISTRY.broadcastMessage(
|
|
242
|
-
msg.
|
|
243
|
-
msg.
|
|
244
|
-
safeExtractSetUIElementMessageBuffers(msg
|
|
213
|
+
msg.ui_element,
|
|
214
|
+
msg.message,
|
|
215
|
+
safeExtractSetUIElementMessageBuffers(msg),
|
|
245
216
|
);
|
|
246
217
|
return;
|
|
247
218
|
|
|
248
219
|
case "remove-ui-elements":
|
|
249
|
-
handleRemoveUIElements(msg
|
|
220
|
+
handleRemoveUIElements(msg);
|
|
250
221
|
return;
|
|
251
222
|
|
|
252
223
|
case "function-call-result":
|
|
253
|
-
FUNCTIONS_REGISTRY.resolve(msg.
|
|
224
|
+
FUNCTIONS_REGISTRY.resolve(msg.function_call_id, msg);
|
|
254
225
|
return;
|
|
255
226
|
|
|
256
227
|
case "cell-op":
|
|
257
|
-
handleCellNotificationeration(msg
|
|
228
|
+
handleCellNotificationeration(msg, actions.handleCellMessage);
|
|
258
229
|
return;
|
|
259
230
|
|
|
260
231
|
case "alert":
|
|
261
232
|
toast({
|
|
262
|
-
title: msg.
|
|
263
|
-
description: renderHTML({ html: msg.
|
|
264
|
-
variant: msg.
|
|
233
|
+
title: msg.title,
|
|
234
|
+
description: renderHTML({ html: msg.description }),
|
|
235
|
+
variant: msg.variant,
|
|
265
236
|
});
|
|
266
237
|
return;
|
|
267
238
|
|
|
268
239
|
case "query-params-append":
|
|
269
|
-
queryParamHandlers.append(msg
|
|
240
|
+
queryParamHandlers.append(msg);
|
|
270
241
|
return;
|
|
271
242
|
case "query-params-set":
|
|
272
|
-
queryParamHandlers.set(msg
|
|
243
|
+
queryParamHandlers.set(msg);
|
|
273
244
|
return;
|
|
274
245
|
case "query-params-delete":
|
|
275
|
-
queryParamHandlers.delete(msg
|
|
246
|
+
queryParamHandlers.delete(msg);
|
|
276
247
|
return;
|
|
277
248
|
case "query-params-clear":
|
|
278
249
|
queryParamHandlers.clear();
|
|
279
250
|
return;
|
|
280
251
|
|
|
281
252
|
case "model-lifecycle":
|
|
282
|
-
handleWidgetMessage(WIDGET_REGISTRY, msg
|
|
253
|
+
handleWidgetMessage(WIDGET_REGISTRY, msg);
|
|
283
254
|
return;
|
|
284
255
|
|
|
285
256
|
case "consumer-capabilities":
|
|
@@ -5,15 +5,16 @@ import { getWorkerRPC } from "@/core/wasm/rpc";
|
|
|
5
5
|
import { Deferred } from "@/utils/Deferred";
|
|
6
6
|
import { throwNotImplemented } from "@/utils/functions";
|
|
7
7
|
import { Logger } from "@/utils/Logger";
|
|
8
|
+
import { jsonParseWithSpecialChar } from "@/utils/json/json-parser";
|
|
8
9
|
import { generateUUID } from "@/utils/uuid";
|
|
9
10
|
import { initialNotebookState, notebookAtom } from "../cells/cells";
|
|
10
|
-
import type { ClientCommand } from "../kernel/messages";
|
|
11
|
+
import type { ClientCommand, NotificationMessage } from "../kernel/messages";
|
|
11
12
|
import type { EditRequests, RunRequests } from "../network/types";
|
|
12
13
|
import { store as defaultStore } from "../state/jotai";
|
|
13
14
|
import { getMarimoExportContext } from "../static/export-context";
|
|
14
15
|
import { createMarimoFile, parseMarimoIslandApps } from "./parse";
|
|
15
16
|
import { islandsInitializedAtom, islandsPendingInitialRunsAtom } from "./state";
|
|
16
|
-
import type {
|
|
17
|
+
import type { WorkerSchema } from "./worker/worker";
|
|
17
18
|
import type { WorkerFactory } from "./worker-factory";
|
|
18
19
|
import { DefaultWorkerFactory } from "./worker-factory";
|
|
19
20
|
|
|
@@ -52,14 +53,14 @@ interface AppSession {
|
|
|
52
53
|
* @example
|
|
53
54
|
* ```ts
|
|
54
55
|
* const bridge = new IslandsPyodideBridge();
|
|
55
|
-
* bridge.
|
|
56
|
+
* bridge.consumeNotifications((notification) => console.log(notification.op));
|
|
56
57
|
* await bridge.initializeApps();
|
|
57
58
|
* ```
|
|
58
59
|
*/
|
|
59
60
|
export class IslandsPyodideBridge implements RunRequests, EditRequests {
|
|
60
61
|
private rpc: ReturnType<typeof getWorkerRPC<WorkerSchema>>;
|
|
61
|
-
private
|
|
62
|
-
| ((
|
|
62
|
+
private notificationConsumer:
|
|
63
|
+
| ((notification: NotificationMessage, sessionGeneration: number) => void)
|
|
63
64
|
| undefined;
|
|
64
65
|
private readonly store: typeof defaultStore;
|
|
65
66
|
private readonly root: Document | Element;
|
|
@@ -110,14 +111,24 @@ export class IslandsPyodideBridge implements RunRequests, EditRequests {
|
|
|
110
111
|
},
|
|
111
112
|
);
|
|
112
113
|
|
|
113
|
-
this.rpc.addMessageListener(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
114
|
+
this.rpc.addMessageListener(
|
|
115
|
+
"notebookEvent",
|
|
116
|
+
({ event, sessionGeneration }) => {
|
|
117
|
+
// A stopped session can still have events in transit after the next
|
|
118
|
+
// app takes ownership of the shared frontend state.
|
|
119
|
+
if (!this.activeSessionGenerations.has(sessionGeneration)) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
// Islands follow only the notebook's marimo notifications.
|
|
123
|
+
const frame = jsonParseWithSpecialChar(event) as {
|
|
124
|
+
event: string;
|
|
125
|
+
data: { marimo?: NotificationMessage };
|
|
126
|
+
};
|
|
127
|
+
if (frame.event === "marimo" && frame.data.marimo) {
|
|
128
|
+
this.notificationConsumer?.(frame.data.marimo, sessionGeneration);
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
);
|
|
121
132
|
}
|
|
122
133
|
|
|
123
134
|
public async initializeApps(): Promise<void> {
|
|
@@ -246,14 +257,14 @@ export class IslandsPyodideBridge implements RunRequests, EditRequests {
|
|
|
246
257
|
await this.rpc.proxy.request.startSession(opts);
|
|
247
258
|
}
|
|
248
259
|
|
|
249
|
-
/**
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
260
|
+
/** Receive each running session's marimo notifications. */
|
|
261
|
+
public consumeNotifications(
|
|
262
|
+
consumer: (
|
|
263
|
+
notification: NotificationMessage,
|
|
264
|
+
sessionGeneration: number,
|
|
265
|
+
) => void,
|
|
254
266
|
): void {
|
|
255
|
-
this.
|
|
256
|
-
this.rpc.proxy.send.consumerReady({});
|
|
267
|
+
this.notificationConsumer = consumer;
|
|
257
268
|
}
|
|
258
269
|
|
|
259
270
|
// ============================================================================
|