@marimo-team/frontend 0.23.16-dev4 → 0.23.16-dev41

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.
Files changed (254) hide show
  1. package/dist/assets/{CellStatus-BalYv0pK.js → CellStatus-C6Cj3oJc.js} +1 -1
  2. package/dist/assets/{ConnectedDataExplorerComponent-DI7mV-Gw.js → ConnectedDataExplorerComponent-CMaZapRd.js} +1 -1
  3. package/dist/assets/{ErrorBoundary-C7_5jjWi.js → ErrorBoundary-DzTD8LVq.js} +1 -1
  4. package/dist/assets/{ImperativeModal-BIavOiUv.js → ImperativeModal-fY-ZfT0b.js} +1 -1
  5. package/dist/assets/{JsonOutput-CkCD-FgM.js → JsonOutput-CyzvjIjx.js} +12 -12
  6. package/dist/assets/{LazyAnyLanguageCodeMirror-sVm_hz8A.js → LazyAnyLanguageCodeMirror-B2JvSXP-.js} +2 -2
  7. package/dist/assets/{MarimoErrorOutput-DO2k2fA5.js → MarimoErrorOutput-CIuzXFFo.js} +4 -4
  8. package/dist/assets/{RSPContexts-CgC81f0I.js → RSPContexts-WiCgGm__.js} +1 -1
  9. package/dist/assets/RenderHTML-Cd-PP5ZR.js +1 -0
  10. package/dist/assets/{RunButton-BKRupqr7.js → RunButton-CnYWedW4.js} +1 -1
  11. package/dist/assets/{add-cell-with-ai-CEZtaZCK.js → add-cell-with-ai-ByOBQT99.js} +8 -8
  12. package/dist/assets/add-connection-dialog-C97ylgk0.js +170 -0
  13. package/dist/assets/{agent-panel-CHB6t7Zy.js → agent-panel-Dxo9WUKV.js} +5 -5
  14. package/dist/assets/ai-model-dropdown-Bvqy98cI.js +5 -0
  15. package/dist/assets/{alert-dialog-BXegNC0I.js → alert-dialog-Bb8Lz8ko.js} +1 -1
  16. package/dist/assets/{any-language-editor-DCpZRrpx.js → any-language-editor--tRHs8C_.js} +1 -1
  17. package/dist/assets/{app-config-button-NrM9ywXA.js → app-config-button-v1lG63C2.js} +1 -1
  18. package/dist/assets/{button-eIihcbUw.js → button-DDGiD1NW.js} +1 -1
  19. package/dist/assets/{cache-panel-wllSTlbM.js → cache-panel-DcQUeUpg.js} +1 -1
  20. package/dist/assets/{capabilities-B09j1Eor.js → capabilities-DoEg0XwL.js} +1 -1
  21. package/dist/assets/{cell-editor-B5JVq7_q.js → cell-editor-BKrHbyX_.js} +16 -16
  22. package/dist/assets/cell-link-w5IbCQV4.js +1 -0
  23. package/dist/assets/cells-DzyDERZy.js +235 -0
  24. package/dist/assets/{chat-display-BG08ltQ3.js → chat-display-Ccgk4vbE.js} +1 -1
  25. package/dist/assets/{chat-panel-P2CzCtXJ.js → chat-panel--53TIc3t.js} +4 -4
  26. package/dist/assets/{chat-ui-fAJZAoTD.js → chat-ui-B5rBxgsw.js} +4 -4
  27. package/dist/assets/{column-preview-Dne1dIt0.js → column-preview-Cb8R9kfl.js} +1 -1
  28. package/dist/assets/{command-CAJLPEBq.js → command-Dqxie4gq.js} +1 -1
  29. package/dist/assets/{command-palette-iOCqUIs1.js → command-palette-B1S9PjZi.js} +1 -1
  30. package/dist/assets/{common-CD6Mj8n6.js → common-CJ3baa6D.js} +1 -1
  31. package/dist/assets/components-DpUIWGaj.js +1 -0
  32. package/dist/assets/config-B-Q7J_6d.js +1 -0
  33. package/dist/assets/{config-COUOIPEq.js → config-BJVx3eBW.js} +1 -1
  34. package/dist/assets/{copy-BtTOqPTS.js → copy-Bxb1_Gtw.js} +1 -1
  35. package/dist/assets/{copy-icon-C2pG0ZNK.js → copy-icon-neDQUo4Q.js} +1 -1
  36. package/dist/assets/{createReducer-C7kZ8zEe.js → createReducer-DGx5Af-C.js} +1 -1
  37. package/dist/assets/{datasource-ySAiC9gr.js → datasource-D_VcQMEn.js} +2 -2
  38. package/dist/assets/{dates-D-kIKDYA.js → dates-C2LWzsCZ.js} +1 -1
  39. package/dist/assets/{dependency-graph-panel-BF23EwcD.js → dependency-graph-panel-DY5lvPDx.js} +3 -3
  40. package/dist/assets/{dialog-D1DEsRZ2.js → dialog-BCVepWLJ.js} +1 -1
  41. package/dist/assets/{dist-ByVeMWkr.js → dist-BLN8PNJV.js} +1 -1
  42. package/dist/assets/dist-CiVShZKM.js +2 -0
  43. package/dist/assets/{documentation-panel-e9Fi9R7e.js → documentation-panel-CGhwxsXK.js} +1 -1
  44. package/dist/assets/download-DpS57jyt.js +9 -0
  45. package/dist/assets/{dropdown-menu-BFZLnWeO.js → dropdown-menu-dHmZR8bI.js} +1 -1
  46. package/dist/assets/{edit-page-7X3HYey7.js → edit-page-DA765yQV.js} +6 -6
  47. package/dist/assets/{error-banner-B6eIlxzg.js → error-banner-BSxEOIn2.js} +1 -1
  48. package/dist/assets/error-entries-CTYMwfsh.js +8 -0
  49. package/dist/assets/{error-panel-DdsUL6b7.js → error-panel-DGAkG5kW.js} +1 -1
  50. package/dist/assets/{es-1D83cgiu.js → es-gYgfF8y5.js} +1 -1
  51. package/dist/assets/{esm-BL7jQmzn.js → esm-B30N1GS0.js} +1 -1
  52. package/dist/assets/{field-BeZbVzXA.js → field-BsxD35VE.js} +1 -1
  53. package/dist/assets/{file-explorer-panel-Ntq1-VbF.js → file-explorer-panel-BKUo-MDh.js} +3 -3
  54. package/dist/assets/{file-icons-Cb54mIL8.js → file-icons-DfWENcb8.js} +1 -1
  55. package/dist/assets/{file-name-input-BWFcK1ey.js → file-name-input-CNVZtm5K.js} +1 -1
  56. package/dist/assets/floating-outline-LitP0wCD.js +1 -0
  57. package/dist/assets/focus-CNKbm-Xz.js +1 -0
  58. package/dist/assets/{form-B6BkSCJb.js → form-nHzLTU1m.js} +2 -2
  59. package/dist/assets/{formats-ClEFGPy-.js → formats-DzmLpc9A.js} +1 -1
  60. package/dist/assets/{formatting-B_41gSF5.js → formatting-CDf6w1Kt.js} +1 -1
  61. package/dist/assets/{fullscreen-dUjPYOmm.js → fullscreen-CTDqNQr6.js} +1 -1
  62. package/dist/assets/{gallery-page-CWQQAYpa.js → gallery-page-CJ3ms1Hn.js} +1 -1
  63. package/dist/assets/{glide-data-editor-lMARFWHS.js → glide-data-editor-j2igs9Y_.js} +1 -1
  64. package/dist/assets/home-page-DM9Z_IJ7.js +4 -0
  65. package/dist/assets/{html-to-image-CwmX28T9.js → html-to-image-JaxFFZcr.js} +2 -2
  66. package/dist/assets/index-C7_REKh1.js +38 -0
  67. package/dist/assets/index-D6Dp_PFj.css +2 -0
  68. package/dist/assets/{input-CqrUjynb.js → input-JxFwu-3G.js} +1 -1
  69. package/dist/assets/kiosk-mode-BumOFEtY.js +1 -0
  70. package/dist/assets/{label-BElwWzf0.js → label-CqjrpwRC.js} +1 -1
  71. package/dist/assets/{layout-CUlZijwG.js → layout-B29hqiiK.js} +5 -5
  72. package/dist/assets/{links-CToBjIIj.js → links-CZr5bjvo.js} +1 -1
  73. package/dist/assets/logs-panel-CQRPYS8j.js +1 -0
  74. package/dist/assets/{markdown-renderer-QvXG0CRk.js → markdown-renderer-sEayY9-m.js} +2 -2
  75. package/dist/assets/{menu-items-DbSLBfXR.js → menu-items-CCi6aOPm.js} +1 -1
  76. package/dist/assets/{mermaid-Bh0flEIb.js → mermaid-CYN0wOyG.js} +1 -1
  77. package/dist/assets/{name-cell-input-C6cukQ9k.js → name-cell-input-B-aj1KH3.js} +1 -1
  78. package/dist/assets/node-sql-parser-Si4oZ2P-.js +68 -0
  79. package/dist/assets/{numbers-CeeaFKqu.js → numbers-rmawRqQP.js} +1 -1
  80. package/dist/assets/{outline-panel-BPlg9_CE.js → outline-panel-BOryk60D.js} +1 -1
  81. package/dist/assets/{packages-panel-BzQF60rG.js → packages-panel-DoYDLty3.js} +1 -1
  82. package/dist/assets/pair-with-agent-modal-BCRSACei.js +4 -0
  83. package/dist/assets/panels-Bb4fIHgH.js +4 -0
  84. package/dist/assets/{popover-DrHQ3KEt.js → popover-Bcz1Zikb.js} +1 -1
  85. package/dist/assets/process-output-d-LEMtGI.js +1 -0
  86. package/dist/assets/{radio-group-CLBjGkt5.js → radio-group-DfioQthW.js} +1 -1
  87. package/dist/assets/{readonly-code-display-D63oRtBP.js → readonly-code-display-C9fu8tvK.js} +1 -1
  88. package/dist/assets/{readonly-python-code-CW_G5e4E.js → readonly-python-code-DHxOnQGj.js} +1 -1
  89. package/dist/assets/{renderShortcut-BZLr8D7H.js → renderShortcut-Bl8_FVn8.js} +1 -1
  90. package/dist/assets/{reveal-component-BLMTmd8T.js → reveal-component-5jf0W625.js} +60 -60
  91. package/dist/assets/{run-page-B6pgDYEJ.js → run-page-BMKx9ld_.js} +1 -1
  92. package/dist/assets/{runs-D51Xwrsk.js → runs-DBTXqJHS.js} +1 -1
  93. package/dist/assets/scratchpad-panel-C8z8vzBX.js +1 -0
  94. package/dist/assets/{scroll-to-bottom-button-Cgr10kaJ.js → scroll-to-bottom-button-C8yfT4wq.js} +1 -1
  95. package/dist/assets/{secrets-panel-Cc5KDBk6.js → secrets-panel-6J6wcuVR.js} +1 -1
  96. package/dist/assets/{select-B5TFNjmU.js → select-BP75_5jJ.js} +1 -1
  97. package/dist/assets/{session-CEFnN9Cq.js → session-BmukRjSi.js} +1 -1
  98. package/dist/assets/{session-panel-Y0Oon0sD.js → session-panel-BVVk-02h.js} +1 -1
  99. package/dist/assets/{share-CYpcX4N4.js → share-852X_cqy.js} +1 -1
  100. package/dist/assets/{skeleton-D3QPxqWC.js → skeleton-Bubr9pIj.js} +1 -1
  101. package/dist/assets/slides-DkEgzTJB.css +1 -0
  102. package/dist/assets/{snippets-panel-CXpGflMO.js → snippets-panel-U2-iok-c.js} +1 -1
  103. package/dist/assets/{spec-CzqcmYQk.js → spec-C7opZZRp.js} +1 -1
  104. package/dist/assets/{state-BvdK8eiw.js → state-D10U2MwA.js} +1 -1
  105. package/dist/assets/{state-WBgc7MiA.js → state-DDag0B_B.js} +1 -1
  106. package/dist/assets/state-DtziTd1T.js +3 -0
  107. package/dist/assets/{state-DBzEQtWz.js → state-DxQhUsG9.js} +1 -1
  108. package/dist/assets/{strings-Djnbwmfl.js → strings--BknHX9C.js} +1 -1
  109. package/dist/assets/{swiper-component-DInvCxhI.js → swiper-component-g8EXE911.js} +1 -1
  110. package/dist/assets/switch-OVajJBPR.js +1 -0
  111. package/dist/assets/{terminal-D3IQBBYo.js → terminal-217O8hlZ.js} +1 -1
  112. package/dist/assets/{textarea-CpFfEUet.js → textarea-Bmzmbbpo.js} +1 -1
  113. package/dist/assets/{tooltip-CFX4fYHU.js → tooltip-4bZlU7jl.js} +1 -1
  114. package/dist/assets/{tooltip-HLb6RxVp.js → tooltip-B7U4xkIN.js} +1 -1
  115. package/dist/assets/{tracing-CKn3gWHw.js → tracing-B5XFvMmV.js} +1 -1
  116. package/dist/assets/{tracing-panel-BU-o_LCd.js → tracing-panel-DnR2bYDe.js} +2 -2
  117. package/dist/assets/{tree-actions-CsC2XmGo.js → tree-actions-Dx9CDaxV.js} +1 -1
  118. package/dist/assets/{useBoolean-D89u30n-.js → useBoolean-CFj86iac.js} +1 -1
  119. package/dist/assets/useCellActionButton-DypR3yDt.js +1 -0
  120. package/dist/assets/{useDeleteCell-EPH4kcG7.js → useDeleteCell-vMXAr3rY.js} +1 -1
  121. package/dist/assets/{useDependencyPanelTab-CZnK7N2L.js → useDependencyPanelTab-CwdwKf7A.js} +1 -1
  122. package/dist/assets/useEventListener-C0195JsF.js +1 -0
  123. package/dist/assets/{useHotkey-DIuRH8Wu.js → useHotkey-DLZvrRZT.js} +1 -1
  124. package/dist/assets/{useIframeCapabilities-Ccb4fvKc.js → useIframeCapabilities-j6fR_dBA.js} +1 -1
  125. package/dist/assets/{useInstallPackage-BRbUAUFn.js → useInstallPackage-WiYBwhUO.js} +1 -1
  126. package/dist/assets/{useInterval-CC0vKpWm.js → useInterval-CWBTUy5W.js} +1 -1
  127. package/dist/assets/useNotebookActions-jWIcmpv0.js +12 -0
  128. package/dist/assets/{useRunCells-CSSF_mJ0.js → useRunCells-C2dvU2jA.js} +1 -1
  129. package/dist/assets/{useSplitCell-9Qz93yPZ.js → useSplitCell-C1tubdNi.js} +1 -1
  130. package/dist/assets/{useTheme-KXqAyDPC.js → useTheme-Bxv9B31g.js} +1 -1
  131. package/dist/assets/{utils-Z80SV4_d.js → utils-BWBBpCkT.js} +1 -1
  132. package/dist/assets/{vega-component-Cie3ag_T.js → vega-component-Db8KjZJG.js} +1 -1
  133. package/dist/assets/{write-secret-modal-DEEn7sZV.js → write-secret-modal-3-v-dHVj.js} +1 -1
  134. package/dist/index.html +68 -68
  135. package/package.json +3 -4
  136. package/src/__mocks__/requests.ts +45 -4
  137. package/src/components/data-table/__tests__/__snapshots__/chart-spec-model.test.ts.snap +174 -21
  138. package/src/components/data-table/__tests__/chart-spec-model.test.ts +102 -1
  139. package/src/components/data-table/column-summary/chart-spec-model.tsx +163 -103
  140. package/src/components/data-table/column-summary/legacy-chart-spec.ts +15 -7
  141. package/src/components/data-table/column-summary/utils.ts +26 -7
  142. package/src/components/data-table/types.ts +1 -1
  143. package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +99 -18
  144. package/src/components/editor/actions/__tests__/pdf-export.test.ts +0 -4
  145. package/src/components/editor/actions/pair-with-agent-commands.ts +21 -10
  146. package/src/components/editor/actions/pair-with-agent-modal.tsx +2 -2
  147. package/src/components/editor/actions/pdf-export.ts +1 -4
  148. package/src/components/editor/actions/useNotebookActions.tsx +7 -13
  149. package/src/components/editor/cell/code/__tests__/cell-editor-activity-lifecycle.test.ts +250 -0
  150. package/src/components/editor/cell/code/cell-editor.tsx +13 -7
  151. package/src/components/editor/chrome/panels/__tests__/logs-panel.test.tsx +25 -0
  152. package/src/components/editor/chrome/panels/logs-panel.tsx +12 -2
  153. package/src/components/editor/connections/storage/__tests__/__snapshots__/as-code.test.ts.snap +50 -0
  154. package/src/components/editor/connections/storage/__tests__/as-code.test.ts +87 -8
  155. package/src/components/editor/connections/storage/as-code.ts +40 -21
  156. package/src/components/editor/connections/storage/schemas.ts +83 -42
  157. package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +1 -1
  158. package/src/components/slides/__tests__/cell-output-block.test.tsx +40 -0
  159. package/src/components/slides/__tests__/slide-cell-view.test.tsx +33 -0
  160. package/src/components/slides/__tests__/slide-scroll-hint.test.tsx +198 -0
  161. package/src/components/slides/reveal-component.tsx +25 -19
  162. package/src/components/slides/slide-cell-view.tsx +1 -1
  163. package/src/components/slides/slide-scroll-hint.tsx +161 -0
  164. package/src/components/slides/slides.css +4 -2
  165. package/src/components/static-html/share-modal.tsx +1 -1
  166. package/src/components/ui/input.tsx +1 -1
  167. package/src/core/cells/__tests__/cells.test.ts +12 -2
  168. package/src/core/cells/__tests__/logs.test.ts +5 -5
  169. package/src/core/cells/cells.ts +17 -4
  170. package/src/core/cells/document-changes.ts +1 -0
  171. package/src/core/cells/logs.ts +14 -4
  172. package/src/core/codemirror/copilot/__tests__/language-server.test.ts +396 -100
  173. package/src/core/codemirror/copilot/__tests__/transport.test.ts +128 -540
  174. package/src/core/codemirror/copilot/language-server.ts +182 -70
  175. package/src/core/codemirror/copilot/transport.ts +15 -207
  176. package/src/core/codemirror/copilot/types.ts +9 -2
  177. package/src/core/codemirror/find-replace/__tests__/navigate.test.ts +42 -30
  178. package/src/core/codemirror/find-replace/navigate.ts +2 -0
  179. package/src/core/codemirror/go-to-definition/__tests__/commands.test.ts +24 -3
  180. package/src/core/codemirror/go-to-definition/commands.ts +3 -0
  181. package/src/core/codemirror/keymaps/__tests__/keymaps.test.ts +31 -2
  182. package/src/core/codemirror/keymaps/keymaps.ts +12 -0
  183. package/src/core/codemirror/language/__tests__/sql.test.ts +443 -61
  184. package/src/core/codemirror/language/languages/python.ts +23 -11
  185. package/src/core/codemirror/language/languages/sql/completion-store.ts +5 -1
  186. package/src/core/codemirror/language/languages/sql/sql.ts +210 -3
  187. package/src/core/codemirror/lsp/__tests__/federated-lsp.test.ts +161 -0
  188. package/src/core/codemirror/lsp/__tests__/log-messages.test.ts +53 -0
  189. package/src/core/codemirror/lsp/__tests__/normalize-markdown-math.test.ts +25 -0
  190. package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +598 -156
  191. package/src/core/codemirror/lsp/__tests__/transports.test.ts +112 -0
  192. package/src/core/codemirror/lsp/federated-lsp.ts +76 -23
  193. package/src/core/codemirror/lsp/log-messages.ts +37 -0
  194. package/src/core/codemirror/lsp/normalize-markdown-math.ts +8 -4
  195. package/src/core/codemirror/lsp/notebook-lsp.ts +220 -56
  196. package/src/core/codemirror/lsp/transports.ts +8 -1
  197. package/src/core/codemirror/lsp/types.ts +68 -8
  198. package/src/core/codemirror/lsp/utils.ts +14 -0
  199. package/src/core/codemirror/utils.ts +28 -0
  200. package/src/core/hotkeys/hotkeys.ts +0 -2
  201. package/src/core/islands/__tests__/bridge.test.ts +107 -0
  202. package/src/core/islands/bridge.ts +16 -0
  203. package/src/core/lsp/__tests__/transport.test.ts +509 -337
  204. package/src/core/lsp/transport.ts +304 -132
  205. package/src/core/mode.ts +10 -0
  206. package/src/core/network/__tests__/api.test.ts +42 -0
  207. package/src/core/network/__tests__/connection.test.ts +45 -0
  208. package/src/core/network/__tests__/requests-lazy.test.ts +32 -1
  209. package/src/core/network/__tests__/requests-network.test.ts +21 -0
  210. package/src/core/network/api.ts +27 -0
  211. package/src/core/network/connection.ts +15 -0
  212. package/src/core/network/requests-lazy.ts +1 -0
  213. package/src/core/network/requests-network.ts +14 -8
  214. package/src/core/network/requests-static.ts +1 -0
  215. package/src/core/network/requests-toasting.tsx +1 -0
  216. package/src/core/network/types.ts +22 -6
  217. package/src/core/rtc/state.ts +9 -0
  218. package/src/core/static/download-html.ts +5 -14
  219. package/src/core/wasm/bridge.ts +4 -2
  220. package/src/core/wasm/worker/types.ts +5 -2
  221. package/src/css/app/codemirror.css +16 -2
  222. package/src/plugins/impl/FormPlugin.tsx +1 -1
  223. package/src/plugins/impl/__tests__/FormPlugin.test.tsx +162 -0
  224. package/src/stories/log-viewer.stories.tsx +12 -6
  225. package/src/utils/__tests__/download.test.tsx +24 -1
  226. package/src/utils/download.ts +11 -6
  227. package/dist/assets/RenderHTML-BCvU9dYz.js +0 -1
  228. package/dist/assets/add-connection-dialog-B-jCRNTN.js +0 -170
  229. package/dist/assets/ai-model-dropdown-DXgLphFa.js +0 -5
  230. package/dist/assets/cell-link-DqBkyAFe.js +0 -1
  231. package/dist/assets/cells-Cf7bHHq3.js +0 -229
  232. package/dist/assets/components-BH6gDVv6.js +0 -1
  233. package/dist/assets/config-BbOTTCYY.js +0 -1
  234. package/dist/assets/dist-BCMBu0rO.js +0 -2
  235. package/dist/assets/download-BomYt3nl.js +0 -9
  236. package/dist/assets/error-entries-Birw-8VX.js +0 -8
  237. package/dist/assets/floating-outline-wz-WSRgP.js +0 -1
  238. package/dist/assets/focus-DiEyfiAG.js +0 -1
  239. package/dist/assets/home-page-DJ4jJsZj.js +0 -4
  240. package/dist/assets/index-A71LAt6h.css +0 -2
  241. package/dist/assets/index-CMZzy-dF.js +0 -38
  242. package/dist/assets/kiosk-mode-ABm3oYgq.js +0 -1
  243. package/dist/assets/logs-panel-iFV4ZJ9b.js +0 -1
  244. package/dist/assets/node-sql-parser-BWgUjcfV.js +0 -68
  245. package/dist/assets/pair-with-agent-modal-CKOYwOYw.js +0 -4
  246. package/dist/assets/panels-Dj45fW-v.js +0 -4
  247. package/dist/assets/process-output-BEhIGfkO.js +0 -1
  248. package/dist/assets/scratchpad-panel-B0mEqBNk.js +0 -1
  249. package/dist/assets/slides-MCbMDtlY.css +0 -1
  250. package/dist/assets/state-BZQc7xxL.js +0 -3
  251. package/dist/assets/switch-CvweaCXq.js +0 -1
  252. package/dist/assets/useCellActionButton-CRfIEVB5.js +0 -1
  253. package/dist/assets/useEventListener-B_w3A283.js +0 -1
  254. package/dist/assets/useNotebookActions-DTXAoukG.js +0 -12
@@ -10,6 +10,7 @@ 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";
13
14
 
14
15
  type Base64String = components["schemas"]["Base64String"];
15
16
  interface TestIslandApp {
@@ -173,6 +174,19 @@ describe("IslandsPyodideBridge", () => {
173
174
  });
174
175
  }
175
176
 
177
+ function sendKernelMessage(sessionGeneration: number) {
178
+ const listener = mockMessageListeners.get("kernelMessage");
179
+ if (!listener) {
180
+ throw new Error("Missing kernel message listener");
181
+ }
182
+ const message = {
183
+ message: "" as IslandsKernelMessage["message"],
184
+ sessionGeneration,
185
+ };
186
+ listener(message as never);
187
+ return message;
188
+ }
189
+
176
190
  async function initializeSingleApp() {
177
191
  mockSingleApp();
178
192
  await bridge.initializeApps();
@@ -281,6 +295,99 @@ describe("IslandsPyodideBridge", () => {
281
295
  });
282
296
 
283
297
  describe("app lifecycle", () => {
298
+ it("ignores messages after a session yields ownership", async () => {
299
+ const consumeMessage = vi.fn();
300
+ bridge.consumeMessages(consumeMessage);
301
+ mockSingleApp();
302
+ await bridge.initializeApps();
303
+
304
+ const firstMessage = sendKernelMessage(1);
305
+ let finishReplacement!: () => void;
306
+ mockReplaceSessionRequest.mockReturnValueOnce(
307
+ new Promise<void>((resolve) => {
308
+ finishReplacement = resolve;
309
+ }),
310
+ );
311
+ setSingleApp("generated app 2");
312
+ const replacement = bridge.initializeApps();
313
+ await vi.waitFor(() =>
314
+ expect(mockReplaceSessionRequest).toHaveBeenCalledOnce(),
315
+ );
316
+ sendKernelMessage(1);
317
+ const currentMessage = sendKernelMessage(2);
318
+
319
+ expect(consumeMessage.mock.calls).toEqual([
320
+ [firstMessage],
321
+ [currentMessage],
322
+ ]);
323
+
324
+ finishReplacement();
325
+ await replacement;
326
+ });
327
+
328
+ it("restores message ownership when replacement fails", async () => {
329
+ const consumeMessage = vi.fn();
330
+ bridge.consumeMessages(consumeMessage);
331
+ mockSingleApp();
332
+ await bridge.initializeApps();
333
+ mockReplaceSessionRequest.mockRejectedValueOnce(
334
+ new Error("replacement failed"),
335
+ );
336
+ setSingleApp("generated app 2");
337
+
338
+ await expect(bridge.initializeApps()).rejects.toThrow(
339
+ "replacement failed",
340
+ );
341
+ const previousMessage = sendKernelMessage(1);
342
+ sendKernelMessage(2);
343
+
344
+ expect(consumeMessage.mock.calls).toEqual([[previousMessage]]);
345
+ });
346
+
347
+ it("ignores messages while their session is stopping", async () => {
348
+ const consumeMessage = vi.fn();
349
+ bridge.consumeMessages(consumeMessage);
350
+ mockSingleApp();
351
+ await bridge.initializeApps();
352
+ let finishStop!: () => void;
353
+ mockStopSessionRequest.mockReturnValueOnce(
354
+ new Promise<void>((resolve) => {
355
+ finishStop = resolve;
356
+ }),
357
+ );
358
+
359
+ const stop = bridge.stopSession();
360
+ await vi.waitFor(() =>
361
+ expect(mockStopSessionRequest).toHaveBeenCalledOnce(),
362
+ );
363
+ sendKernelMessage(1);
364
+
365
+ expect(consumeMessage).not.toHaveBeenCalled();
366
+
367
+ finishStop();
368
+ await stop;
369
+ });
370
+
371
+ it("forwards messages from every app in a multi-app document", async () => {
372
+ const consumeMessage = vi.fn();
373
+ bridge.consumeMessages(consumeMessage);
374
+ mockParseMarimoIslandApps.mockReturnValue([app(), app("app-2")]);
375
+ mockCreateMarimoFile
376
+ .mockReturnValueOnce("generated app 1")
377
+ .mockReturnValueOnce("generated app 2");
378
+ signalWorkerReady();
379
+
380
+ await bridge.initializeApps();
381
+ const firstMessage = sendKernelMessage(1);
382
+ const secondMessage = sendKernelMessage(2);
383
+ sendKernelMessage(3);
384
+
385
+ expect(consumeMessage.mock.calls).toEqual([
386
+ [firstMessage],
387
+ [secondMessage],
388
+ ]);
389
+ });
390
+
284
391
  it("holds controls until the first app session is ready", async () => {
285
392
  setSingleApp();
286
393
 
@@ -66,6 +66,7 @@ export class IslandsPyodideBridge implements RunRequests, EditRequests {
66
66
  private session: AppSession | undefined;
67
67
  private sessionReady = new Deferred<AppSession>();
68
68
  private nextSessionGeneration = 0;
69
+ private readonly activeSessionGenerations = new Set<number>();
69
70
  private appTransition = Promise.resolve();
70
71
  private workerReady = new Deferred<void>();
71
72
 
@@ -110,6 +111,11 @@ export class IslandsPyodideBridge implements RunRequests, EditRequests {
110
111
  );
111
112
 
112
113
  this.rpc.addMessageListener("kernelMessage", (message) => {
114
+ // A stopped session can still have messages in transit after the next
115
+ // app takes ownership of the shared frontend state.
116
+ if (!this.activeSessionGenerations.has(message.sessionGeneration)) {
117
+ return;
118
+ }
113
119
  this.messageConsumer?.(message);
114
120
  });
115
121
  }
@@ -149,6 +155,7 @@ export class IslandsPyodideBridge implements RunRequests, EditRequests {
149
155
  return;
150
156
  }
151
157
  if (apps.length > 0) {
158
+ this.activeSessionGenerations.clear();
152
159
  this.store.set(
153
160
  islandsPendingInitialRunsAtom,
154
161
  new Set(apps.map((_, index) => this.nextSessionGeneration + index + 1)),
@@ -165,6 +172,7 @@ export class IslandsPyodideBridge implements RunRequests, EditRequests {
165
172
  };
166
173
  const previousSession = this.session;
167
174
  const replacesSession = managesSingleApp && previousSession !== undefined;
175
+ this.activeSessionGenerations.add(request.sessionGeneration);
168
176
  if (replacesSession) {
169
177
  this.store.set(notebookAtom, initialNotebookState());
170
178
  }
@@ -186,8 +194,14 @@ export class IslandsPyodideBridge implements RunRequests, EditRequests {
186
194
  this.sessionReady.resolve(this.session);
187
195
  }
188
196
  } catch (error) {
197
+ this.activeSessionGenerations.delete(request.sessionGeneration);
189
198
  if (this.session?.sessionGeneration === request.sessionGeneration) {
190
199
  this.session = previousSession;
200
+ if (previousSession) {
201
+ this.activeSessionGenerations.add(
202
+ previousSession.sessionGeneration,
203
+ );
204
+ }
191
205
  }
192
206
  Logger.error(`Failed to start session for app ${app.id}:`, error);
193
207
  if (managesSingleApp) {
@@ -203,6 +217,7 @@ export class IslandsPyodideBridge implements RunRequests, EditRequests {
203
217
  if (session?.code === undefined || (appId && session.appId !== appId)) {
204
218
  return;
205
219
  }
220
+ this.activeSessionGenerations.delete(session.sessionGeneration);
206
221
  await this.rpc.proxy.request.stopSession({
207
222
  appId: session.appId,
208
223
  sessionGeneration: session.sessionGeneration,
@@ -339,6 +354,7 @@ export class IslandsPyodideBridge implements RunRequests, EditRequests {
339
354
  sendUpdateFile = throwNotImplemented;
340
355
  sendFileDetails = throwNotImplemented;
341
356
  openTutorial = throwNotImplemented;
357
+ getExportAvailability = throwNotImplemented;
342
358
  exportAsHTML = throwNotImplemented;
343
359
  exportAsIPYNB = throwNotImplemented;
344
360
  exportAsMarkdown = throwNotImplemented;