@marimo-team/islands 0.25.3-dev256 → 0.25.3-dev259

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.
@@ -135,7 +135,7 @@ function F(e) {
135
135
  }
136
136
  //#endregion
137
137
  //#region src/components/editor/boundary/ErrorBoundary.tsx
138
- var I = (0, T.lazy)(() => import("./feedback-button-BOfEi2w2.js").then((e) => ({ default: e.FeedbackModal }))), L = (e) => {
138
+ var I = (0, T.lazy)(() => import("./feedback-button-B0-v6Kkx.js").then((e) => ({ default: e.FeedbackModal }))), L = (e) => {
139
139
  let t = (0, w.c)(2), n;
140
140
  return t[0] === e.children ? n = t[1] : (n = /* @__PURE__ */ (0, j.jsx)(O, {
141
141
  FallbackComponent: R,
@@ -17,7 +17,7 @@ function b() {
17
17
  return e.warn("Failed to get version from mount config"), null;
18
18
  }
19
19
  }
20
- var x = b() || "0.25.3-dev256", S = s(x), C = s(!0);
20
+ var x = b() || "0.25.3-dev259", S = s(x), C = s(!0);
21
21
  s(null);
22
22
  //#endregion
23
23
  //#region src/core/wasm/state.ts
@@ -12,7 +12,7 @@ import { A as Re, C as ze, M as Be, S as Ve, T as He, _ as Ue, b as We, c as Ge,
12
12
  import { $ as ot, $t as st, A as ct, At as lt, B as ut, Bt as dt, C as ft, Ct as pt, D as mt, Dt as ht, E as gt, Et as _t, F as vt, Ft as yt, G as bt, Gt as xt, H as St, Ht as Ct, I as wt, It as Tt, Jt as Et, K as Dt, Kt as Ot, L as kt, Lt as At, M as jt, Mt, N as Nt, Nt as Pt, O as Ft, Ot as It, P as Lt, Pt as Rt, Q as zt, Qt as Bt, R as Vt, Rt as Ht, S as Ut, St as Wt, T as Gt, Tt as Kt, U as qt, Ut as Jt, V as Yt, Vt as Xt, W as Zt, Wt as Qt, X as $t, Xt as en, Yt as tn, Z as nn, Zt as rn, _ as an, _n as on, _t as sn, a as cn, an as ln, at as un, b as dn, bn as fn, bt as pn, cn as mn, ct as hn, d as gn, dn as _n, dt as vn, en as yn, et as bn, f as xn, ft as Sn, gn as Cn, gt as wn, h as Tn, hn as En, ht as Dn, i as On, it as kn, j as An, jt as jn, k as Mn, kt as Nn, l as Pn, lt as Fn, mn as In, mt as Ln, n as Rn, nn as zn, nt as Bn, o as Vn, on as Hn, ot as Un, pn as Wn, q as Gn, qt as Kn, rn as qn, rt as Jn, s as Yn, sn as Xn, st as Zn, t as Qn, tn as $n, tt as er, u as tr, un as nr, ut as rr, vn as ir, vt as ar, wt as or, x as sr, xn as cr, xt as lr, yn as ur, yt as dr, z as fr, zt as pr } from "./dropdown-menu-Blu7V6Mk.js";
13
13
  import { a as mr, n as hr, r as gr, t as _r } from "./config-mwEjAmvP.js";
14
14
  import { A as vr, E as yr, G as br, H as xr, I as Sr, Lt as Cr, Nt as wr, Q as Tr, Rt as Er, T as Dr, Tt as Or, U as kr, V as Ar, b as jr, et as Mr, h as Nr, j as Pr, l as Fr, q as Ir, st as Lr, t as Rr, tt as zr, u as Br, wt as Vr, y as Hr, zt as Ur } from "./error-entries-BuIE3Ius.js";
15
- import { n as Wr, t as Gr } from "./ErrorBoundary-Dw222WgJ.js";
15
+ import { n as Wr, t as Gr } from "./ErrorBoundary-Ca_6JrtT.js";
16
16
  import { i as Kr, r as qr, s as Jr, t as Yr } from "./strings-BYJNyKmg.js";
17
17
  import { t as Xr } from "./clsx-CoeGtWvn.js";
18
18
  import { t as Zr } from "./react-dom-DUmH0GXv.js";
@@ -2,7 +2,7 @@ import { a as e } from "./rolldown-runtime-Cb76FRpK.js";
2
2
  import { t } from "./react-sHtZdjeP.js";
3
3
  import { t as n } from "./react-dom-DUmH0GXv.js";
4
4
  import { c as r, l as i, u as a } from "./data-grid-types-0PJ-9N5n.js";
5
- import { a as o, i as s, n as c, r as l } from "./glide-data-editor-DONfgpL5.js";
5
+ import { a as o, i as s, n as c, r as l } from "./glide-data-editor-BSKoRV9o.js";
6
6
  //#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/data-grid-overlay-editor-style.js
7
7
  var u = /* @__PURE__ */ e(t(), 1), d = /* @__PURE__ */ e(n(), 1), f = /*#__PURE__*/ o("div")({
8
8
  name: "DataGridOverlayEditorStyle",
@@ -4,13 +4,13 @@ import { t as r } from "./react-sHtZdjeP.js";
4
4
  import { t as i } from "./compiler-runtime-CldRdSsv.js";
5
5
  import { t as a } from "./copy-icon-DD8bdw4L.js";
6
6
  import { A as o, E as s, I as c, K as l, P as u, T as d, i as f, n as p, zt as m } from "./error-entries-BuIE3Ius.js";
7
- import { n as h, t as ee } from "./globals-LVcmuQDh.js";
7
+ import { n as h, t as ee } from "./globals-CihZM8xT.js";
8
8
  import { t as g } from "./strings-BYJNyKmg.js";
9
9
  import { t as _ } from "./jsx-runtime-3BD1kT0s.js";
10
10
  import { l as te, r as v, x as ne } from "./utils-DXkj82sK.js";
11
11
  import { a as re, i as ie, n as ae, r as oe } from "./dialog-BHYPX87J.js";
12
12
  import { t as se } from "./useAsyncData-DsZMvNXn.js";
13
- import { t as ce } from "./code-visibility-CC97ZBN7.js";
13
+ import { t as ce } from "./code-visibility-DnDS4v5C.js";
14
14
  //#region src/components/ui/skeleton.tsx
15
15
  var y = /* @__PURE__ */ e(r(), 1), b = i(), x = _(), le = (e) => {
16
16
  let n = (0, b.c)(8), r, i;
@@ -6,7 +6,7 @@ import { i as s, n as c, r as l } from "./copy-icon-DD8bdw4L.js";
6
6
  import { c as u, d, i as f, n as p, s as m, t as h } from "./select-CcidPqlM.js";
7
7
  import { d as g, h as _, i as v, l as y, n as b, o as x, q as S, s as C, t as w, u as T } from "./dropdown-menu-Blu7V6Mk.js";
8
8
  import { c as E, d as D, l as O, n as k, o as A, s as ee, t as j, u as te } from "./glide-utils-qbkRZpEy.js";
9
- import { n as ne, t as re } from "./ErrorBoundary-Dw222WgJ.js";
9
+ import { n as ne, t as re } from "./ErrorBoundary-Ca_6JrtT.js";
10
10
  import { i as ie, n as M } from "./strings-BYJNyKmg.js";
11
11
  import { t as N } from "./react-dom-DUmH0GXv.js";
12
12
  import { t as P } from "./jsx-runtime-3BD1kT0s.js";
@@ -7062,7 +7062,7 @@ function rs(e, t, n, r, i) {
7062
7062
  }
7063
7063
  //#endregion
7064
7064
  //#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/data-editor/data-editor.js
7065
- var is = /* @__PURE__ */ e(_r(), 1), as = /* @__PURE__ */ e(xr(), 1), os = K.lazy(async () => await import("./data-grid-overlay-editor-6i6AaX_D.js")), ss = 0;
7065
+ var is = /* @__PURE__ */ e(_r(), 1), as = /* @__PURE__ */ e(xr(), 1), os = K.lazy(async () => await import("./data-grid-overlay-editor-D6cRJh_Y.js")), ss = 0;
7066
7066
  function cs(e) {
7067
7067
  return (0, is.default)((0, as.default)((0, as.default)(e).filter((e) => e.span !== void 0).map((e) => (0, Za.default)((e.span?.[0] ?? 0) + 1, (e.span?.[1] ?? 0) + 1))));
7068
7068
  }
@@ -9293,7 +9293,7 @@ function Vs(e, t, n, r, i) {
9293
9293
  }
9294
9294
  //#endregion
9295
9295
  //#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/cells/number-cell.js
9296
- var Hs = K.lazy(async () => await import("./number-overlay-editor-DAjRYGEz.js")), Us = {
9296
+ var Hs = K.lazy(async () => await import("./number-overlay-editor-BUXqdm7X.js")), Us = {
9297
9297
  getAccessibilityString: (e) => e.data?.toString() ?? "",
9298
9298
  kind: W.Number,
9299
9299
  needsHover: (e) => e.hoverEffect === !0,
@@ -1,6 +1,6 @@
1
1
  import { m as e } from "./tooltip-Bzl4k00l.js";
2
2
  import { l as t } from "./utils-DXkj82sK.js";
3
- import { r as n } from "./code-visibility-CC97ZBN7.js";
3
+ import { r as n } from "./code-visibility-DnDS4v5C.js";
4
4
  var r = e("triangle-alert", [
5
5
  ["path", {
6
6
  d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",
package/dist/main.js CHANGED
@@ -6,7 +6,7 @@ import { i as x, n as S, r as C, t as w } from "./copy-icon-DD8bdw4L.js";
6
6
  import { $ as T, A as E, At as D, B as O, Bt as k, Ct as A, Et as j, F as M, Ft as N, Gt as P, H as F, Ht as I, I as L, Jt as R, Lt as z, M as B, Mt as ee, Pt as te, R as ne, St as re, U as ie, Ut as ae, V as oe, Vt as se, W as ce, Wt as le, Z as ue, _ as de, a as fe, at as pe, b as me, c as he, et as ge, ht as _e, i as ve, jt as ye, kt as be, mt as xe, n as Se, nt as Ce, o as we, ot as Te, pt as Ee, qt as De, rt as Oe, tt as ke, v as Ae, vt as je, w as Me, wt as Ne, x as Pe, xt as Fe, y as Ie, z as Le, zt as Re } from "./html-to-image-BXrAd5q8.js";
7
7
  import { a as ze, d as Be, i as Ve, m as He, n as Ue, o as We, p as Ge, r as Ke, t as qe } from "./tooltip-Bzl4k00l.js";
8
8
  import { D as Je, E as Ye, O as Xe, S as Ze, T as Qe, _ as $e, a as et, c as tt, d as nt, f as rt, g as it, h as at, i as ot, l as st, m as ct, n as lt, o as ut, p as dt, r as ft, s as pt, t as mt, u as ht, v as gt, w as _t, x as vt, y as yt } from "./spec-ZwfZcgsm.js";
9
- import { $t as bt, A as xt, At as St, B as Ct, Bt as wt, C as Tt, Ct as Et, D as Dt, Dt as Ot, E as kt, Et as At, F as jt, Ft as Mt, G as Nt, Gt as Pt, H as Ft, Ht as It, I as Lt, It as Rt, J as zt, Jt as Bt, K as Vt, Kt as Ht, L as Ut, Lt as Wt, M as Gt, Mt as Kt, N as qt, Nt as Jt, O as Yt, Ot as Xt, P as Zt, Pt as Qt, Qt as $t, R as en, Rt as tn, S as nn, T as rn, Tt as an, U as on, Ut as sn, V as cn, Vt as ln, W as un, Wt as dn, X as fn, Xt as pn, Y as mn, Yt as hn, Z as gn, Zt as _n, _ as vn, _t as yn, an as bn, at as xn, b as Sn, bt as Cn, c as wn, cn as Tn, ct as En, d as Dn, dn as On, dt as kn, en as An, f as jn, fn as Mn, ft as Nn, g as Pn, gn as Fn, gt as In, h as Ln, hn as Rn, ht as zn, in as Bn, it as Vn, j as Hn, jt as Un, k as Wn, kt as Gn, ln as Kn, lt as qn, m as Jn, mn as Yn, mt as Xn, nn as Zn, nt as Qn, on as $n, ot as er, p as tr, pn as nr, pt as rr, q as ir, qt as ar, r as or, rn as sr, rt as cr, st as lr, t as ur, tn as dr, tt as fr, u as pr, un as mr, ut as hr, v as gr, vt as _r, w as vr, wt as yr, x as br, y as xr, yt as Sr, z as Cr, zt as wr } from "./common-C2BqegNI.js";
9
+ import { $t as bt, A as xt, At as St, B as Ct, Bt as wt, C as Tt, Ct as Et, D as Dt, Dt as Ot, E as kt, Et as At, F as jt, Ft as Mt, G as Nt, Gt as Pt, H as Ft, Ht as It, I as Lt, It as Rt, J as zt, Jt as Bt, K as Vt, Kt as Ht, L as Ut, Lt as Wt, M as Gt, Mt as Kt, N as qt, Nt as Jt, O as Yt, Ot as Xt, P as Zt, Pt as Qt, Qt as $t, R as en, Rt as tn, S as nn, T as rn, Tt as an, U as on, Ut as sn, V as cn, Vt as ln, W as un, Wt as dn, X as fn, Xt as pn, Y as mn, Yt as hn, Z as gn, Zt as _n, _ as vn, _t as yn, an as bn, at as xn, b as Sn, bt as Cn, c as wn, cn as Tn, ct as En, d as Dn, dn as On, dt as kn, en as An, f as jn, fn as Mn, ft as Nn, g as Pn, gn as Fn, gt as In, h as Ln, hn as Rn, ht as zn, in as Bn, it as Vn, j as Hn, jt as Un, k as Wn, kt as Gn, ln as Kn, lt as qn, m as Jn, mn as Yn, mt as Xn, nn as Zn, nt as Qn, on as $n, ot as er, p as tr, pn as nr, pt as rr, q as ir, qt as ar, r as or, rn as sr, rt as cr, st as lr, t as ur, tn as dr, tt as fr, u as pr, un as mr, ut as hr, v as gr, vt as _r, w as vr, wt as yr, x as br, y as xr, yt as Sr, z as Cr, zt as wr } from "./common-D7-33xPq.js";
10
10
  import { a as Tr, n as Er, s as Dr, t as Or } from "./useLifecycle-GNgvNwI-.js";
11
11
  import { t as kr } from "./check-CSvxZk5I.js";
12
12
  import { A as Ar, C as jr, D as Mr, M as Nr, O as Pr, a as Fr, c as Ir, d as Lr, i as Rr, k as zr, l as Br, n as Vr, o as Hr, r as Ur, s as Wr, t as Gr, w as Kr, x as qr } from "./select-CcidPqlM.js";
@@ -15,8 +15,8 @@ import { c as Di, i as Oi, l as ki, o as Ai, s as ji, t as Mi } from "./config-m
15
15
  import { A as Ni, At as Pi, B as Fi, G as Ii, It as Li, J as Ri, K as zi, N as Bi, Nt as Vi, Ot as Hi, Pt as Ui, R as Wi, St as Gi, T as Ki, Tt as qi, V as Ji, X as Yi, Y as Xi, Z as Zi, _ as Qi, at as $i, c as ea, ct as ta, d as na, g as ra, h as ia, jt as aa, k as oa, kt as sa, lt as ca, m as la, ot as ua, p as da, q as fa, s as pa, ut as ma, xt as ha, z as ga } from "./error-entries-BuIE3Ius.js";
16
16
  import { a as _a, c as va, d as ya, f as ba, i as xa, l as Sa, n as Ca, o as wa, r as Ta, s as Ea, t as Da } from "./process-output-D2ZjxrHe.js";
17
17
  import { a as Oa, c as ka, d as Aa, i as ja, l as Ma, r as Na, u as Pa } from "./glide-utils-qbkRZpEy.js";
18
- import { n as Fa, t as Ia } from "./ErrorBoundary-Dw222WgJ.js";
19
- import { n as La, t as Ra } from "./globals-LVcmuQDh.js";
18
+ import { n as Fa, t as Ia } from "./ErrorBoundary-Ca_6JrtT.js";
19
+ import { n as La, t as Ra } from "./globals-CihZM8xT.js";
20
20
  import { a as za, i as Ba, n as Va, r as Ha, s as Ua, t as Wa } from "./strings-BYJNyKmg.js";
21
21
  import { t as Ga } from "./react-dom-DUmH0GXv.js";
22
22
  import { t as Ka } from "./jsx-runtime-3BD1kT0s.js";
@@ -44,7 +44,7 @@ import { t as Hs } from "./useAsyncData-DsZMvNXn.js";
44
44
  import { t as Us } from "./semaphore-89jsoHtS.js";
45
45
  import { D as Ws, O as Gs } from "./vega-loader.browser-B9Pz0EGP.js";
46
46
  import { a as Ks, n as qs } from "./loader-BVEtQ4F3.js";
47
- import { c as Js, d as Ys, i as Xs, l as Zs, o as Qs, s as $s, t as ec, u as tc } from "./code-visibility-CC97ZBN7.js";
47
+ import { c as Js, d as Ys, i as Xs, l as Zs, o as Qs, s as $s, t as ec, u as tc } from "./code-visibility-DnDS4v5C.js";
48
48
  import { t as nc } from "./useDeepCompareMemoize-KMBBux8C.js";
49
49
  import { t as rc } from "./esm-BgKjMvWw.js";
50
50
  //#region ../node_modules/.pnpm/iconify-icon@2.3.0/node_modules/iconify-icon/dist/iconify-icon.mjs
@@ -3106,7 +3106,7 @@ var Pp = q([
3106
3106
  id: Ap,
3107
3107
  run_id: as([kp, ds()]).describe("The run that owns this execution. Every live execution belongs to exactly one run. May name a run the host has dropped. Null only for a restored result whose run is unknown."),
3108
3108
  runtime_id: as([Dp, ds()]).describe("The runtime that produced this execution. Live when it equals the current runtime's id. Null when the producer is unknown."),
3109
- caused_by: as([Ap, ds()]).describe("The execution in the same run whose code scheduled this one, such as scratch code that ran cells or set a UI element's value. Null for an execution a client requested directly, and for a cell the scheduler ran because of one."),
3109
+ caused_by: as([Ap, ds()]).describe("The execution in the same run whose code was running when this one was scheduled, such as scratch code that ran a cell, set a UI element's value, or wrote state, and the cells that reacted to it. Null for an execution a client requested and for the cells that reacted to one."),
3110
3110
  cell_id: as([Mp, ds()]).describe("The cell this execution belongs to. Null for scratch code, a cell outside the document."),
3111
3111
  code: U().nullable().describe("The submitted code for an execution with no cell. Null for a cell's execution; its source is available through the cell when the host exposes it."),
3112
3112
  code_fingerprint: om.describe("Fingerprint of the code the execution evaluates. Fixed when the execution is published, while it is still queued."),
@@ -12406,7 +12406,7 @@ function _D(e, t) {
12406
12406
  }
12407
12407
  //#endregion
12408
12408
  //#region src/plugins/impl/DataEditorPlugin.tsx
12409
- var vD = J.lazy(() => import("./glide-data-editor-DONfgpL5.js").then((e) => e.t)), yD = eE("marimo-data-editor", { cssStyles: [CE] }).withData(G({
12409
+ var vD = J.lazy(() => import("./glide-data-editor-BSKoRV9o.js").then((e) => e.t)), yD = eE("marimo-data-editor", { cssStyles: [CE] }).withData(G({
12410
12410
  initialValue: G({ edits: K(G({
12411
12411
  rowIdx: W(),
12412
12412
  columnId: U(),
@@ -32194,7 +32194,7 @@ function vH(e) {
32194
32194
  }
32195
32195
  //#endregion
32196
32196
  //#region src/components/editor/renderers/slides-layout/slides-layout.tsx
32197
- var yH = J.lazy(() => import("./reveal-component-DgRl_ANV.js")), bH = (e) => {
32197
+ var yH = J.lazy(() => import("./reveal-component-4D-84xpO.js")), bH = (e) => {
32198
32198
  let t = (0, X.c)(33), { layout: n, setLayout: r, cells: i, mode: a } = e, o = jo(Wo), s = a === "read" || o, c = jo(ha) > 1, [l, u] = (0, J.useState)(null), d;
32199
32199
  t[0] !== i || t[1] !== n ? (d = gR(i, n), t[0] = i, t[1] = n, t[2] = d) : d = t[2];
32200
32200
  let { slideCells: f, skippedIds: p, noOutputIds: m, slideTypes: h, startCellIndex: g } = d, _;
@@ -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-DONfgpL5.js";
3
+ import { a as n } from "./glide-data-editor-BSKoRV9o.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",
@@ -3,7 +3,7 @@ import { c as t, g as n, h as r, m as i, t as a } from "./button-0-RqY1DW.js";
3
3
  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-Bzl4k00l.js";
6
- import { $ as u, Q as d, et as f, i as p, l as m, n as h, on as g, r as _, sn as v, t as y, u as b, un as x } from "./common-C2BqegNI.js";
6
+ import { $ as u, Q as d, et as f, i as p, l as m, n as h, on as g, r as _, sn as v, t as y, u as b, un as x } from "./common-D7-33xPq.js";
7
7
  import { M as S } from "./select-CcidPqlM.js";
8
8
  import { Y as ee } from "./dropdown-menu-Blu7V6Mk.js";
9
9
  import { Pt as C } from "./error-entries-BuIE3Ius.js";
@@ -11,7 +11,7 @@ import { t as w } from "./jsx-runtime-3BD1kT0s.js";
11
11
  import { r as T } from "./use-restore-focus-CmflVLWJ.js";
12
12
  import { D as E, t as D, x as O } from "./utils-DXkj82sK.js";
13
13
  import { o as k } from "./static-state-BldGd99T.js";
14
- import { a as A, n as te, t as ne } from "./code-visibility-CC97ZBN7.js";
14
+ import { a as A, n as te, t as ne } from "./code-visibility-DnDS4v5C.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.25.3-dev256",
3
+ "version": "0.25.3-dev259",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
4
4
  import { Deferred } from "@/utils/Deferred";
5
+ import { atom } from "jotai";
5
6
 
6
7
  const {
7
8
  mockBridge,
@@ -101,6 +102,9 @@ vi.mock("@/core/wasm/store", () => ({
101
102
  // Import after all mocks are set up
102
103
  import { store } from "@/core/state/jotai";
103
104
  import { initialModeAtom } from "@/core/mode";
105
+ import type { NotebookClient } from "@marimo-team/client";
106
+ import type { NotebookReplica } from "@/core/notebook/replica";
107
+ import { activeNotebookReplicaAtom } from "@/core/session/active-notebook";
104
108
  import { fallbackFileStore, notebookFileStore } from "../store";
105
109
  import { getWasmWorkerName, PyodideBridge } from "../bridge";
106
110
 
@@ -258,6 +262,108 @@ it("cancels a pending notebook subscription before its RPC response", async () =
258
262
  }
259
263
  });
260
264
 
265
+ it("raises the interrupt buffer for a running run before the worker takes the call", async () => {
266
+ vi.clearAllMocks();
267
+ store.set(initialModeAtom, "read");
268
+ rpcListeners.initialized();
269
+ const run = {
270
+ id: "run-1",
271
+ notebook_id: "n1",
272
+ runtime_id: "r1",
273
+ cells: [],
274
+ status: "running",
275
+ outcome: null,
276
+ started_at: "2026-10-01T09:20:11Z",
277
+ completed_at: null,
278
+ };
279
+ const replicaWith = (status: string) =>
280
+ ({
281
+ executionsAtom: atom({
282
+ runs: new Map([["run-1", { ...run, status }]]),
283
+ executions: new Map(),
284
+ latest: new Map(),
285
+ }),
286
+ }) as unknown as NotebookReplica;
287
+ const interrupt = vi
288
+ .spyOn(PyodideBridge.INSTANCE, "sendInterrupt")
289
+ .mockResolvedValue(null);
290
+ mockNotebookCall.mockResolvedValue({ status: 202, body: run });
291
+ try {
292
+ const backend = await PyodideBridge.INSTANCE.createNotebookBackend();
293
+ // The backend narrows the client to editing until the editor runs through the host.
294
+ const notebook = backend.notebook("n1") as unknown as NotebookClient;
295
+
296
+ store.set(activeNotebookReplicaAtom, replicaWith("running"));
297
+ expect((await notebook.interrupt("run-1")).ok).toBe(true);
298
+ expect(interrupt).toHaveBeenCalledOnce();
299
+ expect(mockNotebookCall).toHaveBeenCalledOnce();
300
+ expect(interrupt.mock.invocationCallOrder[0]).toBeLessThan(
301
+ mockNotebookCall.mock.invocationCallOrder[0],
302
+ );
303
+
304
+ store.set(activeNotebookReplicaAtom, replicaWith("queued"));
305
+ expect((await notebook.interrupt("run-1")).ok).toBe(true);
306
+ expect(interrupt).toHaveBeenCalledOnce();
307
+ expect(mockNotebookCall).toHaveBeenCalledTimes(2);
308
+ } finally {
309
+ interrupt.mockRestore();
310
+ store.set(activeNotebookReplicaAtom, null);
311
+ store.set(initialModeAtom, undefined);
312
+ }
313
+ });
314
+
315
+ it("raises the interrupt buffer once a run interrupted while queued starts", async () => {
316
+ vi.clearAllMocks();
317
+ store.set(initialModeAtom, "read");
318
+ rpcListeners.initialized();
319
+ const run = {
320
+ id: "run-1",
321
+ notebook_id: "n1",
322
+ runtime_id: "r1",
323
+ cells: [],
324
+ status: "queued",
325
+ outcome: null,
326
+ started_at: null,
327
+ completed_at: null,
328
+ };
329
+ store.set(activeNotebookReplicaAtom, {
330
+ executionsAtom: atom({
331
+ runs: new Map([["run-1", run]]),
332
+ executions: new Map(),
333
+ latest: new Map(),
334
+ }),
335
+ } as unknown as NotebookReplica);
336
+ const interrupt = vi
337
+ .spyOn(PyodideBridge.INSTANCE, "sendInterrupt")
338
+ .mockResolvedValue(null);
339
+ mockNotebookCall.mockResolvedValue({ status: 202, body: run });
340
+ const deliver = (status: string) =>
341
+ rpcListeners.notebookEvent({
342
+ id: "sub",
343
+ event: JSON.stringify({
344
+ event: "run",
345
+ data: { run: { ...run, status } },
346
+ }),
347
+ });
348
+ try {
349
+ const backend = await PyodideBridge.INSTANCE.createNotebookBackend();
350
+ const notebook = backend.notebook("n1") as unknown as NotebookClient;
351
+ expect((await notebook.interrupt("run-1")).ok).toBe(true);
352
+ expect(interrupt).not.toHaveBeenCalled();
353
+
354
+ // The worker took the run before the cancellation reached it.
355
+ deliver("running");
356
+ expect(interrupt).toHaveBeenCalledOnce();
357
+ deliver("running");
358
+ deliver("completed");
359
+ expect(interrupt).toHaveBeenCalledOnce();
360
+ } finally {
361
+ interrupt.mockRestore();
362
+ store.set(activeNotebookReplicaAtom, null);
363
+ store.set(initialModeAtom, undefined);
364
+ }
365
+ });
366
+
261
367
  describe("getWasmWorkerName", () => {
262
368
  afterEach(() => {
263
369
  delete (window as unknown as { __MARIMO_HAS_WASM_CONTROLLER__?: boolean })
@@ -78,6 +78,7 @@ async function startWorker(subscribing = Promise.resolve()) {
78
78
  ),
79
79
  unsubscribe: (id: string) => subscribers.delete(id),
80
80
  set_persistence: vi.fn(),
81
+ set_package_loader: vi.fn(),
81
82
  destroy: vi.fn(),
82
83
  };
83
84
  const bridge = { notebook, destroy: vi.fn() };
@@ -14,6 +14,7 @@ import { once } from "@/utils/once";
14
14
  import { generateUUID } from "@/utils/uuid";
15
15
  import { createModuleWorker } from "@/utils/worker";
16
16
  import { notebookIsRunningAtom } from "../cells/cells";
17
+ import { activeNotebookReplicaAtom } from "../session/active-notebook";
17
18
  import { flushDocument } from "../cells/document";
18
19
  import { createWasmNotebookBackend } from "../transports/wasm";
19
20
  import type { ClientCommand } from "../kernel/messages";
@@ -73,6 +74,8 @@ export class PyodideBridge implements RunRequests, EditRequests {
73
74
  private saveRpc: SaveWorker | undefined;
74
75
  private notebookConsumers = new Map<string, (event: unknown) => void>();
75
76
  private interruptBuffer?: Uint8Array;
77
+ /** Runs asked to stop before they ran; the buffer is raised once they do. */
78
+ private pendingInterrupts = new Set<string>();
76
79
 
77
80
  public initialized = new Deferred<void>();
78
81
 
@@ -135,7 +138,9 @@ export class PyodideBridge implements RunRequests, EditRequests {
135
138
  this.rpc.send.bootstrap(runtimeConfig);
136
139
 
137
140
  this.rpc.addMessageListener("notebookEvent", ({ id, event }) => {
138
- this.notebookConsumers.get(id)?.(JSON.parse(event));
141
+ const parsed: unknown = JSON.parse(event);
142
+ this.raisePendingInterrupt(parsed);
143
+ this.notebookConsumers.get(id)?.(parsed);
139
144
  });
140
145
 
141
146
  // Listeners
@@ -247,10 +252,55 @@ export class PyodideBridge implements RunRequests, EditRequests {
247
252
  throw error;
248
253
  }
249
254
  },
250
- call: (call) => this.rpc.proxy.request.notebookCall(call),
255
+ call: (call) => {
256
+ if (call.operation === "runtime.interrupt") {
257
+ // The worker cannot take the call while a cell runs; raise the
258
+ // interrupt there first. A queued run is cancelled by the worker,
259
+ // unless it starts before the call arrives: then it is raised
260
+ // when the run is reported running.
261
+ if (this.isRunning(call.params.run_id)) {
262
+ void this.sendInterrupt();
263
+ } else {
264
+ this.pendingInterrupts.add(call.params.run_id);
265
+ }
266
+ }
267
+ return this.rpc.proxy.request.notebookCall(call);
268
+ },
251
269
  });
252
270
  }
253
271
 
272
+ /** Raise the buffer for a pending interrupt whose run has started. */
273
+ private raisePendingInterrupt(event: unknown): void {
274
+ if (this.pendingInterrupts.size === 0) {
275
+ return;
276
+ }
277
+ const frame = event as {
278
+ event?: string;
279
+ data?: { run?: { id: string; status: string } };
280
+ };
281
+ const run = frame.event === "run" ? frame.data?.run : undefined;
282
+ if (run === undefined || !this.pendingInterrupts.has(run.id)) {
283
+ return;
284
+ }
285
+ if (run.status === "running") {
286
+ this.pendingInterrupts.delete(run.id);
287
+ void this.sendInterrupt();
288
+ } else if (run.status === "completed") {
289
+ this.pendingInterrupts.delete(run.id);
290
+ }
291
+ }
292
+
293
+ /** Whether the host reports `runId` as running, so a cell is executing. */
294
+ private isRunning(runId: string): boolean {
295
+ const replica = store.get(activeNotebookReplicaAtom);
296
+ if (replica === null) {
297
+ return false;
298
+ }
299
+ return (
300
+ store.get(replica.executionsAtom).runs.get(runId)?.status === "running"
301
+ );
302
+ }
303
+
254
304
  public sendRename: EditRequests["sendRename"] = async ({ filename }) => {
255
305
  if (filename === null) {
256
306
  return null;
@@ -130,6 +130,7 @@ export type SerializedBridge = {
130
130
  set_persistence(
131
131
  persist: (contents: string, filename: string) => Promise<void>,
132
132
  ): void;
133
+ set_package_loader(load: (code: string) => Promise<void>): void;
133
134
  destroy(): void;
134
135
  };
135
136
  };
@@ -82,6 +82,32 @@ async function getNotebook() {
82
82
  return session.bridge.notebook;
83
83
  }
84
84
 
85
+ /** Load the packages `code` imports, with marimo's SQL heuristics. */
86
+ async function loadPackagesForCode(code: string) {
87
+ const span = t.startSpan("loadPackages");
88
+ await pyodideReadyPromise; // Make sure loading is done
89
+
90
+ if (shouldLoadDuckDBPackages(code)) {
91
+ // Add pandas and duckdb to the code for mo.sql and for remote duckdb sources
92
+ code = `import pandas\n${code}`;
93
+ code = `import duckdb\n${code}`;
94
+ code = `import sqlglot\n${code}`;
95
+
96
+ // Polars + SQL requires pyarrow, and installing
97
+ // after notebook load does not work. As a heuristic,
98
+ // if it appears that the notebook uses polars, add pyarrow.
99
+ if (code.includes("polars")) {
100
+ code = `import pyarrow\n${code}`;
101
+ }
102
+ }
103
+
104
+ await self.pyodide.loadPackagesFromImports(code, {
105
+ messageCallback: Logger.log,
106
+ errorCallback: Logger.error,
107
+ });
108
+ span.end();
109
+ }
110
+
85
111
  const requestHandler = createRPCRequestHandler({
86
112
  notebookSubscribe: (request: { id: string; cursor: string | null }) => {
87
113
  let canceled = false;
@@ -172,6 +198,8 @@ const requestHandler = createRPCRequestHandler({
172
198
  self.pyodide.FS.writeFile(WasmFileSystem.NOTEBOOK_FILENAME, contents);
173
199
  await rpc.proxy.request.persistNotebook({ filename, contents });
174
200
  });
201
+ // Host runs name cells, so the worker loads their imports itself.
202
+ notebook.set_package_loader(loadPackagesForCode);
175
203
  } finally {
176
204
  notebook.destroy();
177
205
  }
@@ -190,33 +218,7 @@ const requestHandler = createRPCRequestHandler({
190
218
  return;
191
219
  },
192
220
 
193
- /**
194
- * Load packages
195
- */
196
- loadPackages: async (code: string) => {
197
- const span = t.startSpan("loadPackages");
198
- await pyodideReadyPromise; // Make sure loading is done
199
-
200
- if (shouldLoadDuckDBPackages(code)) {
201
- // Add pandas and duckdb to the code for mo.sql and for remote duckdb sources
202
- code = `import pandas\n${code}`;
203
- code = `import duckdb\n${code}`;
204
- code = `import sqlglot\n${code}`;
205
-
206
- // Polars + SQL requires pyarrow, and installing
207
- // after notebook load does not work. As a heuristic,
208
- // if it appears that the notebook uses polars, add pyarrow.
209
- if (code.includes("polars")) {
210
- code = `import pyarrow\n${code}`;
211
- }
212
- }
213
-
214
- await self.pyodide.loadPackagesFromImports(code, {
215
- messageCallback: Logger.log,
216
- errorCallback: Logger.error,
217
- });
218
- span.end();
219
- },
221
+ loadPackages: (code: string) => loadPackagesForCode(code),
220
222
 
221
223
  /**
222
224
  * Read a file