@marimo-team/frontend 0.24.3-dev57 → 0.24.3-dev60
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/assets/{ConnectedDataExplorerComponent-D_HEi6SB.js → ConnectedDataExplorerComponent-BSvwB270.js} +1 -1
- package/dist/assets/{ErrorBoundary-Bhro9JSh.js → ErrorBoundary-TsEoIDRr.js} +2 -2
- package/dist/assets/{LazyAnyLanguageCodeMirror-BFspjPgP.js → LazyAnyLanguageCodeMirror-BSKy620l.js} +2 -2
- package/dist/assets/{RunButton-BeaDmdtc.js → RunButton-Dul9caMU.js} +2 -2
- package/dist/assets/__vite-browser-external-BKSyd8Ok.js +1 -0
- package/dist/assets/__vite-browser-external-ZTY8EBdt.js +1 -0
- package/dist/assets/{abnfDiagram-VCTEODGH-BAjtYACw.js → abnfDiagram-VCTEODGH-Cjyff0Dj.js} +1 -1
- package/dist/assets/{add-cell-with-ai-X0N6vwOW.js → add-cell-with-ai-BhDPL21V.js} +1 -1
- package/dist/assets/{agent-panel-CIM-IFq-.js → agent-panel-CYUY6ClW.js} +1 -1
- package/dist/assets/{ai-model-dropdown-QGHX7XPi.js → ai-model-dropdown-CnDRzQfQ.js} +1 -1
- package/dist/assets/{any-language-editor-yOCyRjna.js → any-language-editor-C6lBHXNY.js} +1 -1
- package/dist/assets/{app-config-button-D43jGigF.js → app-config-button-9I3Y-dHh.js} +1 -1
- package/dist/assets/{architectureDiagram-5GKGNRK7-DfSmckYy.js → architectureDiagram-5GKGNRK7-BBYvsdwV.js} +1 -1
- package/dist/assets/{blockDiagram-I7D4REHJ-mPibg6ZN.js → blockDiagram-I7D4REHJ-XAi6eabU.js} +1 -1
- package/dist/assets/{cache-panel-lZPSQ4BV.js → cache-panel-DKXBQfDt.js} +1 -1
- package/dist/assets/{chat-display-BpJhJI_w.js → chat-display-BlIEWw3Q.js} +1 -1
- package/dist/assets/{chat-panel-DCH1nWE4.js → chat-panel-C_XE2bS-.js} +1 -1
- package/dist/assets/{chat-ui-ensnmKXA.js → chat-ui-BRq__jk9.js} +1 -1
- package/dist/assets/{chunk-IMKFNOWR-BeZYLc2s.js → chunk-IMKFNOWR-bmBDB0cN.js} +1 -1
- package/dist/assets/{chunk-SHT3W25Y-C9YhY993.js → chunk-SHT3W25Y-DFrgoI5E.js} +1 -1
- package/dist/assets/{chunk-SVP7TREG-DUwuAIVi.js → chunk-SVP7TREG-usES5uzt.js} +1 -1
- package/dist/assets/{chunk-TICWLB2K-D5MXcnaz.js → chunk-TICWLB2K-DmYGvTDJ.js} +1 -1
- package/dist/assets/{classDiagram-ZZMXUADV-o1Skvo75.js → classDiagram-ZZMXUADV-8oWUrTSA.js} +1 -1
- package/dist/assets/{classDiagram-v2-VYDZK3BY-o1Skvo75.js → classDiagram-v2-VYDZK3BY-8oWUrTSA.js} +1 -1
- package/dist/assets/{code-visibility-B8W4VSJV.js → code-visibility-ChrgD3_b.js} +1 -1
- package/dist/assets/{command-palette-C35q00no.js → command-palette-D_70H77j.js} +1 -1
- package/dist/assets/{common-DYiVXqaU.js → common-BfKDjmi0.js} +1 -1
- package/dist/assets/{components-WfL_9jWE.js → components-BFKAEF3R.js} +1 -1
- package/dist/assets/{components-C_3lUq6C.js → components-DyBejhtt.js} +1 -1
- package/dist/assets/{cynefinDiagram-5FMLGOSQ-QneBbdEB.js → cynefinDiagram-5FMLGOSQ-CGpZt6Mr.js} +1 -1
- package/dist/assets/{dagre-4DjPZ8Kk.js → dagre-6C2JCFmZ.js} +1 -1
- package/dist/assets/{dagre-GXQ25YYZ-DVhNQEKL.js → dagre-GXQ25YYZ-DwPg2iyK.js} +1 -1
- package/dist/assets/{data-grid-overlay-editor-BT4qp8We.js → data-grid-overlay-editor-BHzBco-G.js} +1 -1
- package/dist/assets/{dependency-graph-panel-OqJ2JRYq.js → dependency-graph-panel-DxbTpdSy.js} +1 -1
- package/dist/assets/{diagram-S7CK7UJ4-Bk2juH7G.js → diagram-S7CK7UJ4-D3rnjIpt.js} +1 -1
- package/dist/assets/{diagram-UQ7AKVKN-BI_rMglh.js → diagram-UQ7AKVKN--mvb4nAR.js} +1 -1
- package/dist/assets/{diagram-VX7I27RA-Cy-onqpN.js → diagram-VX7I27RA-DLd2xbGj.js} +1 -1
- package/dist/assets/{diagram-Z3DM3KII-C0k-oa81.js → diagram-Z3DM3KII-DCQ7kQxu.js} +1 -1
- package/dist/assets/{documentation-panel-BlAZk4Jr.js → documentation-panel-D1oy9mJX.js} +1 -1
- package/dist/assets/{ebnfDiagram-PWID7BFC-DCiwc4mM.js → ebnfDiagram-PWID7BFC-BEPSCGTU.js} +1 -1
- package/dist/assets/{edit-page-DrxCBzWK.js → edit-page-KRRlhyb9.js} +4 -4
- package/dist/assets/{erDiagram-RLTQ6QDP-C2-AGHtK.js → erDiagram-RLTQ6QDP-DVP8JuYC.js} +1 -1
- package/dist/assets/{error-panel-D-Ikit7K.js → error-panel-DSHUnrwV.js} +1 -1
- package/dist/assets/{feedback-button-D17bPV9H.js → feedback-button-C-rqcadY.js} +1 -1
- package/dist/assets/{file-explorer-panel-Cjb-LABC.js → file-explorer-panel-W4vRK0IK.js} +1 -1
- package/dist/assets/{file-name-input-HiYjWzVE.js → file-name-input-BQURTAD0.js} +1 -1
- package/dist/assets/{flowDiagram-HODETNUW-D2FahSKZ.js → flowDiagram-HODETNUW-CxI8veho.js} +1 -1
- package/dist/assets/{gallery-page-C9UmXdun.js → gallery-page-CCiwxBoC.js} +1 -1
- package/dist/assets/{glide-data-editor-BElEmfL6.js → glide-data-editor-YdUhj2-W.js} +4 -4
- package/dist/assets/{graphlib-e-CVq8N0.js → graphlib-Dqk_AhmH.js} +1 -1
- package/dist/assets/has-BXV7_iwm.js +1 -0
- package/dist/assets/{home-page-C8l1PiEi.js → home-page-Bhfe_Ooj.js} +1 -1
- package/dist/assets/{index-BnWsVdKv.js → index-kGHM0O4l.js} +33 -33
- package/dist/assets/{infoDiagram-27XIBGKW-D2MysUR6.js → infoDiagram-27XIBGKW-vkRRAmNG.js} +1 -1
- package/dist/assets/{ishikawaDiagram-5VMMS53U-BZQnLTia.js → ishikawaDiagram-5VMMS53U-DwnkA3qK.js} +1 -1
- package/dist/assets/{kanban-definition-UXKFOSKX-hny44WI2.js → kanban-definition-UXKFOSKX-DTM4IJzH.js} +1 -1
- package/dist/assets/{logs-panel-DGo_I_kd.js → logs-panel-CpmZ43Xd.js} +1 -1
- package/dist/assets/{mermaid-CAGiWnbd.js → mermaid-BYaoBhgB.js} +4 -4
- package/dist/assets/{mindmap-definition-YA3MSWOX-DH_bqGco.js → mindmap-definition-YA3MSWOX-BtrIeuN2.js} +1 -1
- package/dist/assets/{number-overlay-editor-n4cP6N13.js → number-overlay-editor-uOD-jX8J.js} +1 -1
- package/dist/assets/{outline-panel-Bl3kWL7j.js → outline-panel-DHBB8jr2.js} +1 -1
- package/dist/assets/{packages-panel-CvTC28vZ.js → packages-panel-Ba0BIKw-.js} +1 -1
- package/dist/assets/{panels-DYbGO44_.js → panels-CVG8esk7.js} +3 -3
- package/dist/assets/{pegDiagram-XKGWAZYB-ByYXHO-0.js → pegDiagram-XKGWAZYB-72Js5lku.js} +1 -1
- package/dist/assets/{pieDiagram-E7YTZNPT-XxdDfUai.js → pieDiagram-E7YTZNPT-Bj3RCLfN.js} +1 -1
- package/dist/assets/{process-output-CJHLffFJ.js → process-output-cqVv_LQh.js} +1 -1
- package/dist/assets/{railroadDiagram-O6MQD6OU-DCfuAbdF.js → railroadDiagram-O6MQD6OU-B10zJ5xk.js} +1 -1
- package/dist/assets/{requirementDiagram-BXWQKSXE-AoR603VE.js → requirementDiagram-BXWQKSXE-BF4LA-gO.js} +1 -1
- package/dist/assets/{reveal-component-8Kf0tlOj.js → reveal-component-Cvagx4WC.js} +1 -1
- package/dist/assets/{run-page-CJs4PiA_.js → run-page-O9BXJwTz.js} +1 -1
- package/dist/assets/save-worker-CMa6Cvnx.js +113 -0
- package/dist/assets/{scratchpad-panel-Dxp9V8UA.js → scratchpad-panel-CJacTdzi.js} +1 -1
- package/dist/assets/{secrets-panel-3jXUYrm1.js → secrets-panel-BvtVCy_x.js} +1 -1
- package/dist/assets/{sequenceDiagram-WJ2MYXX4-CHL06MGN.js → sequenceDiagram-WJ2MYXX4-Cz9d4L3l.js} +1 -1
- package/dist/assets/{session-panel-D0nQ2246.js → session-panel-C7l7daPJ.js} +1 -1
- package/dist/assets/{snippets-panel-C1oD4sDh.js → snippets-panel-BP4UI0bt.js} +1 -1
- package/dist/assets/{stateDiagram-D77RDMKH-CNotp8N7.js → stateDiagram-D77RDMKH-BYVxo4-Y.js} +1 -1
- package/dist/assets/{stateDiagram-v2-MP3YSRHH-B2NDwtxJ.js → stateDiagram-v2-MP3YSRHH-BO2Qvl2_.js} +1 -1
- package/dist/assets/{swimlanes-42K2YHIH-B1vpqUPJ.js → swimlanes-42K2YHIH-nJMxtt_e.js} +1 -1
- package/dist/assets/{swimlanesDiagram-VR7AAH4N-DQ96Bb1b.js → swimlanesDiagram-VR7AAH4N-2_BeIocM.js} +1 -1
- package/dist/assets/{swiper-component-9BxMpIGW.js → swiper-component-VHJ-MBld.js} +1 -1
- package/dist/assets/{terminal-C817f0XA.js → terminal-DfWCJPGz.js} +1 -1
- package/dist/assets/{timeline-definition-24CTP7MA-f2WGeuCS.js → timeline-definition-24CTP7MA-LaRikknb.js} +1 -1
- package/dist/assets/{tracing-N4r80Qnj.js → tracing-njWlk06F.js} +1 -1
- package/dist/assets/{tracing-panel-DJ5Tel2h.js → tracing-panel-BFMefFq8.js} +2 -2
- package/dist/assets/{useCellActionButton-DBEVl09G.js → useCellActionButton-Cie43jOq.js} +1 -1
- package/dist/assets/{vega-component-Cf5N-jf9.js → vega-component-CrJlHxXg.js} +1 -1
- package/dist/assets/{vega-embed-container-Calgzj1L.js → vega-embed-container-DkDtQznq.js} +1 -1
- package/dist/assets/{vennDiagram-4TSXK5OY-DvdpgX0t.js → vennDiagram-4TSXK5OY-y3U656IE.js} +1 -1
- package/dist/assets/{wardleyDiagram-VM6X3IG4-Bakfup0z.js → wardleyDiagram-VM6X3IG4-COdor5IG.js} +1 -1
- package/dist/assets/{worker-k3VMDfLg.js → worker-B8c-1v-F.js} +4 -4
- package/dist/assets/{xychartDiagram-S5SC5T6Z-DbNCrNYl.js → xychartDiagram-S5SC5T6Z-BHauP6L-.js} +1 -1
- package/dist/index.html +3 -3
- package/package.json +1 -1
- package/src/components/editor/cell/__tests__/toolbar.test.tsx +73 -0
- package/src/components/editor/cell/toolbar.tsx +11 -0
- package/src/core/wasm/__tests__/bootstrap.test.ts +63 -0
- package/src/core/wasm/__tests__/bridge.test.ts +8 -0
- package/src/core/wasm/__tests__/runtime-config.test.ts +58 -0
- package/src/core/wasm/bridge.ts +9 -1
- package/src/core/wasm/rpc.ts +2 -0
- package/src/core/wasm/runtime-config.ts +27 -0
- package/src/core/wasm/worker/bootstrap.ts +21 -11
- package/src/core/wasm/worker/save-worker.ts +7 -0
- package/src/core/wasm/worker/types.ts +7 -4
- package/src/core/wasm/worker/worker.ts +6 -0
- package/dist/assets/__vite-browser-external-59-mUMQX.js +0 -1
- package/dist/assets/__vite-browser-external-CtTeG-HY.js +0 -1
- package/dist/assets/has-CVn0p2Rx.js +0 -1
- package/dist/assets/save-worker-Di2CE_lj.js +0 -113
package/dist/assets/{xychartDiagram-S5SC5T6Z-DbNCrNYl.js → xychartDiagram-S5SC5T6Z-BHauP6L-.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{t as e}from"./linear-0eij_aAG.js";import{n as t}from"./ordinal-BdBDtYTt.js";import{t as n}from"./range-EplFIxc7.js";import{v as r}from"./step-CriubqJO.js";import{i}from"./chunk-75Z2AOVW-DA_lihEi.js";import{n as a}from"./init-ZlXS9mIS.js";import{n as o}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{t as s}from"./src-Cyu5G-Tr.js";import{D as c,H as l,K as u,U as d,a as f,b as p,c as m,f as h,v as g,w as _,y as v,z as y}from"./chunk-DU6HZSFF-J-califE.js";import"./chunk-PWAF6VOD-CrFPAGFi.js";import{t as b}from"./chunk-GMAD6QVW-mXoq4V-T.js";import{p as x}from"./mermaid-
|
|
1
|
+
import{t as e}from"./linear-0eij_aAG.js";import{n as t}from"./ordinal-BdBDtYTt.js";import{t as n}from"./range-EplFIxc7.js";import{v as r}from"./step-CriubqJO.js";import{i}from"./chunk-75Z2AOVW-DA_lihEi.js";import{n as a}from"./init-ZlXS9mIS.js";import{n as o}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{t as s}from"./src-Cyu5G-Tr.js";import{D as c,H as l,K as u,U as d,a as f,b as p,c as m,f as h,v as g,w as _,y as v,z as y}from"./chunk-DU6HZSFF-J-califE.js";import"./chunk-PWAF6VOD-CrFPAGFi.js";import{t as b}from"./chunk-GMAD6QVW-mXoq4V-T.js";import{p as x}from"./mermaid-BYaoBhgB.js";function S(){var e=t().unknown(void 0),r=e.domain,i=e.range,o=0,s=1,c,l,u=!1,d=0,f=0,p=.5;delete e.unknown;function m(){var e=r().length,t=s<o,a=t?s:o,m=t?o:s;c=(m-a)/Math.max(1,e-d+f*2),u&&(c=Math.floor(c)),a+=(m-a-c*(e-d))*p,l=c*(1-d),u&&(a=Math.round(a),l=Math.round(l));var h=n(e).map(function(e){return a+c*e});return i(t?h.reverse():h)}return e.domain=function(e){return arguments.length?(r(e),m()):r()},e.range=function(e){return arguments.length?([o,s]=e,o=+o,s=+s,m()):[o,s]},e.rangeRound=function(e){return[o,s]=e,o=+o,s=+s,u=!0,m()},e.bandwidth=function(){return l},e.step=function(){return c},e.round=function(e){return arguments.length?(u=!!e,m()):u},e.padding=function(e){return arguments.length?(d=Math.min(1,f=+e),m()):d},e.paddingInner=function(e){return arguments.length?(d=Math.min(1,e),m()):d},e.paddingOuter=function(e){return arguments.length?(f=+e,m()):f},e.align=function(e){return arguments.length?(p=Math.max(0,Math.min(1,e)),m()):p},e.copy=function(){return S(r(),[o,s]).round(u).paddingInner(d).paddingOuter(f).align(p)},a.apply(m(),arguments)}var C=(function(){var e=o(function(e,t,n,r){for(n||={},r=e.length;r--;n[e[r]]=t);return n},`o`),t=[1,10,12,14,16,18,19,21,23],n=[2,6],r=[1,3],i=[1,5],a=[1,6],s=[1,7],c=[1,5,10,12,14,16,18,19,21,23,36,37,38],l=[1,25],u=[1,26],d=[1,28],f=[1,29],p=[1,30],m=[1,31],h=[1,32],g=[1,33],_=[1,34],v=[1,35],y=[1,36],b=[1,37],x=[1,43],S=[1,42],C=[1,47],w=[1,50],T=[1,10,12,14,16,18,19,21,23,36,37,38],E=[1,10,12,14,16,18,19,21,23,24,26,28,29,36,37,38],D=[1,10,12,14,16,18,19,21,23,24,26,28,29,36,37,38,42,43,44,45,46,47,48,49,50,51],O=[1,65],k=[26,28],A={trace:o(function(){},`trace`),yy:{},symbols_:{error:2,start:3,eol:4,XYCHART:5,chartConfig:6,document:7,CHART_ORIENTATION:8,statement:9,title:10,text:11,X_AXIS:12,parseXAxis:13,Y_AXIS:14,parseYAxis:15,LINE:16,plotData:17,BAR:18,acc_title:19,acc_title_value:20,acc_descr:21,acc_descr_value:22,acc_descr_multiline_value:23,SQUARE_BRACES_START:24,dataPoints:25,SQUARE_BRACES_END:26,dataPoint:27,COMMA:28,NUMBER_WITH_DECIMAL:29,STR:30,xAxisData:31,bandData:32,ARROW_DELIMITER:33,commaSeparatedTexts:34,yAxisData:35,NEWLINE:36,SEMI:37,EOF:38,alphaNum:39,MD_STR:40,alphaNumToken:41,AMP:42,NUM:43,ALPHA:44,PLUS:45,EQUALS:46,MULT:47,DOT:48,BRKT:49,MINUS:50,UNDERSCORE:51,$accept:0,$end:1},terminals_:{2:`error`,5:`XYCHART`,8:`CHART_ORIENTATION`,10:`title`,12:`X_AXIS`,14:`Y_AXIS`,16:`LINE`,18:`BAR`,19:`acc_title`,20:`acc_title_value`,21:`acc_descr`,22:`acc_descr_value`,23:`acc_descr_multiline_value`,24:`SQUARE_BRACES_START`,26:`SQUARE_BRACES_END`,28:`COMMA`,29:`NUMBER_WITH_DECIMAL`,30:`STR`,33:`ARROW_DELIMITER`,36:`NEWLINE`,37:`SEMI`,38:`EOF`,40:`MD_STR`,42:`AMP`,43:`NUM`,44:`ALPHA`,45:`PLUS`,46:`EQUALS`,47:`MULT`,48:`DOT`,49:`BRKT`,50:`MINUS`,51:`UNDERSCORE`},productions_:[0,[3,2],[3,3],[3,2],[3,1],[6,1],[7,0],[7,2],[9,2],[9,2],[9,2],[9,2],[9,2],[9,3],[9,2],[9,3],[9,2],[9,2],[9,1],[17,3],[25,3],[25,1],[27,2],[27,1],[13,1],[13,2],[13,1],[31,1],[31,3],[32,3],[34,3],[34,1],[15,1],[15,2],[15,1],[35,3],[4,1],[4,1],[4,1],[11,1],[11,1],[11,1],[39,1],[39,2],[41,1],[41,1],[41,1],[41,1],[41,1],[41,1],[41,1],[41,1],[41,1],[41,1]],performAction:o(function(e,t,n,r,i,a,o){var s=a.length-1;switch(i){case 5:r.setOrientation(a[s]);break;case 9:r.setDiagramTitle(a[s].text.trim());break;case 12:r.setLineData({text:``,type:`text`},a[s]);break;case 13:r.setLineData(a[s-1],a[s]);break;case 14:r.setBarData({text:``,type:`text`},a[s]);break;case 15:r.setBarData(a[s-1],a[s]);break;case 16:this.$=a[s].trim(),r.setAccTitle(this.$);break;case 17:case 18:this.$=a[s].trim(),r.setAccDescription(this.$);break;case 19:this.$=a[s-1];break;case 20:case 30:this.$=[a[s-2],...a[s]];break;case 21:case 31:this.$=[a[s]];break;case 22:this.$={value:Number(a[s-1]),label:a[s]};break;case 23:this.$={value:Number(a[s]),label:``};break;case 24:r.setXAxisTitle(a[s]);break;case 25:r.setXAxisTitle(a[s-1]);break;case 26:r.setXAxisTitle({type:`text`,text:``});break;case 27:r.setXAxisBand(a[s]);break;case 28:r.setXAxisRangeData(Number(a[s-2]),Number(a[s]));break;case 29:this.$=a[s-1];break;case 32:r.setYAxisTitle(a[s]);break;case 33:r.setYAxisTitle(a[s-1]);break;case 34:r.setYAxisTitle({type:`text`,text:``});break;case 35:r.setYAxisRangeData(Number(a[s-2]),Number(a[s]));break;case 39:this.$={text:a[s],type:`text`};break;case 40:this.$={text:a[s],type:`text`};break;case 41:this.$={text:a[s],type:`markdown`};break;case 42:this.$=a[s];break;case 43:this.$=a[s-1]+``+a[s]}},`anonymous`),table:[e(t,n,{3:1,4:2,7:4,5:r,36:i,37:a,38:s}),{1:[3]},e(t,n,{4:2,7:4,3:8,5:r,36:i,37:a,38:s}),e(t,n,{4:2,7:4,6:9,3:10,5:r,8:[1,11],36:i,37:a,38:s}),{1:[2,4],9:12,10:[1,13],12:[1,14],14:[1,15],16:[1,16],18:[1,17],19:[1,18],21:[1,19],23:[1,20]},e(c,[2,36]),e(c,[2,37]),e(c,[2,38]),{1:[2,1]},e(t,n,{4:2,7:4,3:21,5:r,36:i,37:a,38:s}),{1:[2,3]},e(c,[2,5]),e(t,[2,7],{4:22,36:i,37:a,38:s}),{11:23,30:l,39:24,40:u,41:27,42:d,43:f,44:p,45:m,46:h,47:g,48:_,49:v,50:y,51:b},{11:39,13:38,24:x,29:S,30:l,31:40,32:41,39:24,40:u,41:27,42:d,43:f,44:p,45:m,46:h,47:g,48:_,49:v,50:y,51:b},{11:45,15:44,29:C,30:l,35:46,39:24,40:u,41:27,42:d,43:f,44:p,45:m,46:h,47:g,48:_,49:v,50:y,51:b},{11:49,17:48,24:w,30:l,39:24,40:u,41:27,42:d,43:f,44:p,45:m,46:h,47:g,48:_,49:v,50:y,51:b},{11:52,17:51,24:w,30:l,39:24,40:u,41:27,42:d,43:f,44:p,45:m,46:h,47:g,48:_,49:v,50:y,51:b},{20:[1,53]},{22:[1,54]},e(T,[2,18]),{1:[2,2]},e(T,[2,8]),e(T,[2,9]),e(E,[2,39],{41:55,42:d,43:f,44:p,45:m,46:h,47:g,48:_,49:v,50:y,51:b}),e(E,[2,40]),e(E,[2,41]),e(D,[2,42]),e(D,[2,44]),e(D,[2,45]),e(D,[2,46]),e(D,[2,47]),e(D,[2,48]),e(D,[2,49]),e(D,[2,50]),e(D,[2,51]),e(D,[2,52]),e(D,[2,53]),e(T,[2,10]),e(T,[2,24],{32:41,31:56,24:x,29:S}),e(T,[2,26]),e(T,[2,27]),{33:[1,57]},{11:59,30:l,34:58,39:24,40:u,41:27,42:d,43:f,44:p,45:m,46:h,47:g,48:_,49:v,50:y,51:b},e(T,[2,11]),e(T,[2,32],{35:60,29:C}),e(T,[2,34]),{33:[1,61]},e(T,[2,12]),{17:62,24:w},{25:63,27:64,29:O},e(T,[2,14]),{17:66,24:w},e(T,[2,16]),e(T,[2,17]),e(D,[2,43]),e(T,[2,25]),{29:[1,67]},{26:[1,68]},{26:[2,31],28:[1,69]},e(T,[2,33]),{29:[1,70]},e(T,[2,13]),{26:[1,71]},{26:[2,21],28:[1,72]},e(k,[2,23],{30:[1,73]}),e(T,[2,15]),e(T,[2,28]),e(T,[2,29]),{11:59,30:l,34:74,39:24,40:u,41:27,42:d,43:f,44:p,45:m,46:h,47:g,48:_,49:v,50:y,51:b},e(T,[2,35]),e(T,[2,19]),{25:75,27:64,29:O},e(k,[2,22]),{26:[2,30]},{26:[2,20]}],defaultActions:{8:[2,1],10:[2,3],21:[2,2],74:[2,30],75:[2,20]},parseError:o(function(e,t){if(t.recoverable)this.trace(e);else{var n=Error(e);throw n.hash=t,n}},`parseError`),parse:o(function(e){var t=this,n=[0],r=[],i=[null],a=[],s=this.table,c=``,l=0,u=0,d=0,f=2,p=1,m=a.slice.call(arguments,1),h=Object.create(this.lexer),g={yy:{}};for(var _ in this.yy)Object.prototype.hasOwnProperty.call(this.yy,_)&&(g.yy[_]=this.yy[_]);h.setInput(e,g.yy),g.yy.lexer=h,g.yy.parser=this,h.yylloc===void 0&&(h.yylloc={});var v=h.yylloc;a.push(v);var y=h.options&&h.options.ranges;this.parseError=typeof g.yy.parseError==`function`?g.yy.parseError:Object.getPrototypeOf(this).parseError;function b(e){n.length-=2*e,i.length-=e,a.length-=e}o(b,`popStack`);function x(){var e=r.pop()||h.lex()||p;return typeof e!=`number`&&(e instanceof Array&&(r=e,e=r.pop()),e=t.symbols_[e]||e),e}o(x,`lex`);for(var S,C,w,T,E,D={},O,k,A,j;;){if(w=n[n.length-1],this.defaultActions[w]?T=this.defaultActions[w]:(S??=x(),T=s[w]&&s[w][S]),T===void 0||!T.length||!T[0]){var M=``;for(O in j=[],s[w])this.terminals_[O]&&O>f&&j.push(`'`+this.terminals_[O]+`'`);M=h.showPosition?`Parse error on line `+(l+1)+`:
|
|
2
2
|
`+h.showPosition()+`
|
|
3
3
|
Expecting `+j.join(`, `)+`, got '`+(this.terminals_[S]||S)+`'`:`Parse error on line `+(l+1)+`: Unexpected `+(S==p?`end of input`:`'`+(this.terminals_[S]||S)+`'`),this.parseError(M,{text:h.match,token:this.terminals_[S]||S,line:h.yylineno,loc:v,expected:j})}if(T[0]instanceof Array&&T.length>1)throw Error(`Parse Error: multiple actions possible at state: `+w+`, token: `+S);switch(T[0]){case 1:n.push(S),i.push(h.yytext),a.push(h.yylloc),n.push(T[1]),S=null,C?(S=C,C=null):(u=h.yyleng,c=h.yytext,l=h.yylineno,v=h.yylloc,d>0&&d--);break;case 2:if(k=this.productions_[T[1]][1],D.$=i[i.length-k],D._$={first_line:a[a.length-(k||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(k||1)].first_column,last_column:a[a.length-1].last_column},y&&(D._$.range=[a[a.length-(k||1)].range[0],a[a.length-1].range[1]]),E=this.performAction.apply(D,[c,u,l,g.yy,T[1],i,a].concat(m)),E!==void 0)return E;k&&(n=n.slice(0,-1*k*2),i=i.slice(0,-1*k),a=a.slice(0,-1*k)),n.push(this.productions_[T[1]][0]),i.push(D.$),a.push(D._$),A=s[n[n.length-2]][n[n.length-1]],n.push(A);break;case 3:return!0}}return!0},`parse`)};A.lexer=(function(){return{EOF:1,parseError:o(function(e,t){if(this.yy.parser)this.yy.parser.parseError(e,t);else throw Error(e)},`parseError`),setInput:o(function(e,t){return this.yy=t||this.yy||{},this._input=e,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match=``,this.conditionStack=[`INITIAL`],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},`setInput`),input:o(function(){var e=this._input[0];return this.yytext+=e,this.yyleng++,this.offset++,this.match+=e,this.matched+=e,e.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),e},`input`),unput:o(function(e){var t=e.length,n=e.split(/(?:\r\n?|\n)/g);this._input=e+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-t),this.offset-=t;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-t},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-t]),this.yyleng=this.yytext.length,this},`unput`),more:o(function(){return this._more=!0,this},`more`),reject:o(function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError(`Lexical error on line `+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
|
|
4
4
|
`+this.showPosition(),{text:``,token:null,line:this.yylineno});return this},`reject`),less:o(function(e){this.unput(this.match.slice(e))},`less`),pastInput:o(function(){var e=this.matched.substr(0,this.matched.length-this.match.length);return(e.length>20?`...`:``)+e.substr(-20).replace(/\n/g,``)},`pastInput`),upcomingInput:o(function(){var e=this.match;return e.length<20&&(e+=this._input.substr(0,20-e.length)),(e.substr(0,20)+(e.length>20?`...`:``)).replace(/\n/g,``)},`upcomingInput`),showPosition:o(function(){var e=this.pastInput(),t=Array(e.length+1).join(`-`);return e+this.upcomingInput()+`
|
package/dist/index.html
CHANGED
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
<marimo-server-token data-token="{{ server_token }}" hidden></marimo-server-token>
|
|
67
67
|
<!-- /TODO -->
|
|
68
68
|
<title>{{ title }}</title>
|
|
69
|
-
<script type="module" crossorigin src="./assets/index-
|
|
69
|
+
<script type="module" crossorigin src="./assets/index-kGHM0O4l.js"></script>
|
|
70
70
|
<link rel="modulepreload" crossorigin href="./assets/rolldown-runtime-B0Z9INg1.js">
|
|
71
71
|
<link rel="modulepreload" crossorigin href="./assets/react-CUdNIagt.js">
|
|
72
72
|
<link rel="modulepreload" crossorigin href="./assets/compiler-runtime-BQ9S8nyo.js">
|
|
@@ -144,11 +144,11 @@
|
|
|
144
144
|
<link rel="modulepreload" crossorigin href="./assets/copy-RyCOE8jo.js">
|
|
145
145
|
<link rel="modulepreload" crossorigin href="./assets/copy-BhJktFeI.js">
|
|
146
146
|
<link rel="modulepreload" crossorigin href="./assets/copy-icon-DFhUGBjO.js">
|
|
147
|
-
<link rel="modulepreload" crossorigin href="./assets/ErrorBoundary-
|
|
147
|
+
<link rel="modulepreload" crossorigin href="./assets/ErrorBoundary-TsEoIDRr.js">
|
|
148
148
|
<link rel="modulepreload" crossorigin href="./assets/config-CMqNngzA.js">
|
|
149
149
|
<link rel="modulepreload" crossorigin href="./assets/chevron-right-DOPs2jx8.js">
|
|
150
150
|
<link rel="modulepreload" crossorigin href="./assets/dropdown-menu-VuyoeQOD.js">
|
|
151
|
-
<link rel="modulepreload" crossorigin href="./assets/LazyAnyLanguageCodeMirror-
|
|
151
|
+
<link rel="modulepreload" crossorigin href="./assets/LazyAnyLanguageCodeMirror-BSKy620l.js">
|
|
152
152
|
<link rel="modulepreload" crossorigin href="./assets/hat-glasses-DVgK5i5l.js">
|
|
153
153
|
<link rel="modulepreload" crossorigin href="./assets/package-BeYhVWvM.js">
|
|
154
154
|
<link rel="modulepreload" crossorigin href="./assets/errors-D9vyuMar.js">
|
package/package.json
CHANGED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
4
|
+
import { describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { ToolbarItem } from "../toolbar";
|
|
6
|
+
|
|
7
|
+
describe("ToolbarItem keyboard activation", () => {
|
|
8
|
+
it.each(["Enter", " "])(
|
|
9
|
+
"keeps native %s activation out of cell navigation and calls the consumer handler",
|
|
10
|
+
(key) => {
|
|
11
|
+
const onCellKeyDown = vi.fn();
|
|
12
|
+
const onKeyDown = vi.fn();
|
|
13
|
+
render(
|
|
14
|
+
<div onKeyDown={onCellKeyDown}>
|
|
15
|
+
<ToolbarItem tooltip={null} onKeyDown={onKeyDown}>
|
|
16
|
+
Run
|
|
17
|
+
</ToolbarItem>
|
|
18
|
+
</div>,
|
|
19
|
+
);
|
|
20
|
+
const button = screen.getByRole("button", { name: "Run" });
|
|
21
|
+
|
|
22
|
+
expect(fireEvent.keyDown(button, { key })).toBe(true);
|
|
23
|
+
expect(onCellKeyDown).not.toHaveBeenCalled();
|
|
24
|
+
expect(onKeyDown).toHaveBeenCalledOnce();
|
|
25
|
+
expect(onKeyDown.mock.calls[0][0].defaultPrevented).toBe(false);
|
|
26
|
+
},
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
it.each([
|
|
30
|
+
{ key: "Enter", ctrlKey: true },
|
|
31
|
+
{ key: "Enter", metaKey: true },
|
|
32
|
+
{ key: "Enter", shiftKey: true },
|
|
33
|
+
{ key: "Enter", altKey: true },
|
|
34
|
+
{ key: " ", ctrlKey: true },
|
|
35
|
+
{ key: "ArrowLeft" },
|
|
36
|
+
{ key: "ArrowRight" },
|
|
37
|
+
{ key: "Tab" },
|
|
38
|
+
{ key: "Escape" },
|
|
39
|
+
])("preserves propagation for %j", (event) => {
|
|
40
|
+
const onCellKeyDown = vi.fn();
|
|
41
|
+
render(
|
|
42
|
+
<div onKeyDown={onCellKeyDown}>
|
|
43
|
+
<ToolbarItem tooltip={null}>Run</ToolbarItem>
|
|
44
|
+
</div>,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
expect(fireEvent.keyDown(screen.getByRole("button"), event)).toBe(true);
|
|
48
|
+
expect(onCellKeyDown).toHaveBeenCalledOnce();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("does not submit forms and preserves disabled and mouse-focus behavior", () => {
|
|
52
|
+
const onClick = vi.fn();
|
|
53
|
+
const { rerender } = render(
|
|
54
|
+
<ToolbarItem tooltip={null} onClick={onClick}>
|
|
55
|
+
Run
|
|
56
|
+
</ToolbarItem>,
|
|
57
|
+
);
|
|
58
|
+
const button = screen.getByRole("button");
|
|
59
|
+
expect(button).toHaveAttribute("type", "button");
|
|
60
|
+
expect(fireEvent.mouseDown(button)).toBe(false);
|
|
61
|
+
fireEvent.click(button);
|
|
62
|
+
expect(onClick).toHaveBeenCalledOnce();
|
|
63
|
+
|
|
64
|
+
rerender(
|
|
65
|
+
<ToolbarItem tooltip={null} onClick={onClick} disabled={true}>
|
|
66
|
+
Run
|
|
67
|
+
</ToolbarItem>,
|
|
68
|
+
);
|
|
69
|
+
expect(button).toBeDisabled();
|
|
70
|
+
fireEvent.click(button);
|
|
71
|
+
expect(onClick).toHaveBeenCalledOnce();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -43,8 +43,19 @@ export const ToolbarItem: React.FC<ToolbarItemProps> = ({
|
|
|
43
43
|
}) => {
|
|
44
44
|
const content = (
|
|
45
45
|
<button
|
|
46
|
+
type="button"
|
|
46
47
|
disabled={disabled}
|
|
47
48
|
{...rest}
|
|
49
|
+
onKeyDown={(evt) => {
|
|
50
|
+
// Preserve native button activation without triggering cell navigation.
|
|
51
|
+
if (
|
|
52
|
+
!Events.hasModifier(evt) &&
|
|
53
|
+
(evt.key === "Enter" || evt.key === " ")
|
|
54
|
+
) {
|
|
55
|
+
evt.stopPropagation();
|
|
56
|
+
}
|
|
57
|
+
rest.onKeyDown?.(evt);
|
|
58
|
+
}}
|
|
48
59
|
onClick={(evt) => {
|
|
49
60
|
if (!disabled) {
|
|
50
61
|
rest.onClick?.(evt);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { loadPyodide } from "pyodide";
|
|
4
|
+
import type { PyodideInterface } from "pyodide";
|
|
5
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
6
|
+
import { DefaultWasmController } from "../worker/bootstrap";
|
|
7
|
+
|
|
8
|
+
vi.mock("pyodide", () => ({ loadPyodide: vi.fn() }));
|
|
9
|
+
vi.mock("../worker/getMarimoWheel", () => ({
|
|
10
|
+
getMarimoWheel: () => "marimo-base",
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
const micropip = { set_index_urls: vi.fn(), destroy: vi.fn() };
|
|
14
|
+
const pyodide = { pyimport: vi.fn(() => micropip) };
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
vi.clearAllMocks();
|
|
18
|
+
vi.mocked(loadPyodide).mockResolvedValue(
|
|
19
|
+
pyodide as unknown as PyodideInterface,
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe("WASM runtime sources", () => {
|
|
24
|
+
it("preserves the default runtime sources", async () => {
|
|
25
|
+
await new DefaultWasmController().bootstrap({
|
|
26
|
+
version: "0.24.2",
|
|
27
|
+
pyodideVersion: "v314.0.0",
|
|
28
|
+
});
|
|
29
|
+
expect(loadPyodide).toHaveBeenCalledWith(
|
|
30
|
+
expect.objectContaining({
|
|
31
|
+
indexURL: "https://cdn.jsdelivr.net/pyodide/v314.0.0/full/",
|
|
32
|
+
packageBaseUrl: "https://cdn.jsdelivr.net/pyodide/v314.0.0/full/",
|
|
33
|
+
lockFileURL:
|
|
34
|
+
"https://wasm.marimo.app/pyodide-lock.json?v=0.24.2&pyodide=v314.0.0",
|
|
35
|
+
}),
|
|
36
|
+
);
|
|
37
|
+
expect(pyodide.pyimport).not.toHaveBeenCalled();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("configures runtime and package sources before returning the interpreter", async () => {
|
|
41
|
+
const controller = new DefaultWasmController();
|
|
42
|
+
await controller.bootstrap({
|
|
43
|
+
version: "0.24.2",
|
|
44
|
+
pyodideVersion: "v314.0.0",
|
|
45
|
+
pyodideIndexUrl: "https://example.com/runtime/",
|
|
46
|
+
pyodideLockfileUrl: "https://example.com/lock.json",
|
|
47
|
+
pypiIndexUrl: "https://example.com/pypi/{package_name}/json",
|
|
48
|
+
});
|
|
49
|
+
expect(loadPyodide).toHaveBeenCalledWith(
|
|
50
|
+
expect.objectContaining({
|
|
51
|
+
indexURL: "https://example.com/runtime/",
|
|
52
|
+
packageBaseUrl: "https://example.com/runtime/",
|
|
53
|
+
lockFileURL: "https://example.com/lock.json",
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
expect(pyodide.pyimport).toHaveBeenCalledWith("micropip");
|
|
57
|
+
expect(micropip.set_index_urls).toHaveBeenCalledWith(
|
|
58
|
+
"https://example.com/pypi/{package_name}/json",
|
|
59
|
+
);
|
|
60
|
+
expect(micropip.destroy).toHaveBeenCalledOnce();
|
|
61
|
+
expect(controller.requirePyodide).toBe(pyodide);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -9,12 +9,14 @@ const {
|
|
|
9
9
|
mockNotebookReadFile,
|
|
10
10
|
mockReadNotebook,
|
|
11
11
|
mockSaveNotebook,
|
|
12
|
+
mockBootstrap,
|
|
12
13
|
rpcListeners,
|
|
13
14
|
} = vi.hoisted(() => ({
|
|
14
15
|
mockBridge: vi.fn(),
|
|
15
16
|
mockNotebookReadFile: vi.fn(),
|
|
16
17
|
mockReadNotebook: vi.fn(),
|
|
17
18
|
mockSaveNotebook: vi.fn(),
|
|
19
|
+
mockBootstrap: vi.fn(),
|
|
18
20
|
rpcListeners: {} as Record<string, () => void>,
|
|
19
21
|
}));
|
|
20
22
|
|
|
@@ -40,6 +42,7 @@ vi.stubGlobal("URL", MockURL);
|
|
|
40
42
|
|
|
41
43
|
vi.mock("@/core/wasm/rpc", () => ({
|
|
42
44
|
getWorkerRPC: () => ({
|
|
45
|
+
send: { bootstrap: mockBootstrap },
|
|
43
46
|
proxy: {
|
|
44
47
|
request: {
|
|
45
48
|
bridge: mockBridge,
|
|
@@ -122,6 +125,11 @@ describe("PyodideBridge.readCode", () => {
|
|
|
122
125
|
|
|
123
126
|
await PyodideBridge.INSTANCE.readCode();
|
|
124
127
|
|
|
128
|
+
expect(mockBootstrap).toHaveBeenCalledWith({
|
|
129
|
+
pyodideIndexUrl: undefined,
|
|
130
|
+
pyodideLockfileUrl: undefined,
|
|
131
|
+
pypiIndexUrl: undefined,
|
|
132
|
+
});
|
|
125
133
|
expect(mockNotebookReadFile).not.toHaveBeenCalled();
|
|
126
134
|
});
|
|
127
135
|
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { afterEach, assert, describe, expect, it } from "vitest";
|
|
4
|
+
import { getWasmRuntimeConfig } from "../runtime-config";
|
|
5
|
+
|
|
6
|
+
afterEach(() => {
|
|
7
|
+
document.head.innerHTML = "";
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
describe("getWasmRuntimeConfig", () => {
|
|
11
|
+
it("uses runtime defaults when no URLs are configured", () => {
|
|
12
|
+
expect(getWasmRuntimeConfig()).toEqual({
|
|
13
|
+
pyodideIndexUrl: undefined,
|
|
14
|
+
pyodideLockfileUrl: undefined,
|
|
15
|
+
pypiIndexUrl: undefined,
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("resolves URLs against the page base and preserves micropip placeholders", () => {
|
|
20
|
+
document.head.innerHTML = `
|
|
21
|
+
<base href="https://example.com/blog/post/">
|
|
22
|
+
<marimo-wasm
|
|
23
|
+
data-pyodide-index-url="../runtime/"
|
|
24
|
+
data-pyodide-lockfile-url="/locks/pyodide.json?v=1&x=2"
|
|
25
|
+
data-pypi-index-url="https://packages.example.com/{package_name}/json"
|
|
26
|
+
></marimo-wasm>`;
|
|
27
|
+
expect(getWasmRuntimeConfig()).toEqual({
|
|
28
|
+
pyodideIndexUrl: "https://example.com/blog/runtime/",
|
|
29
|
+
pyodideLockfileUrl: "https://example.com/locks/pyodide.json?v=1&x=2",
|
|
30
|
+
pypiIndexUrl: "https://packages.example.com/{package_name}/json",
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it.each(["pyodideIndexUrl", "pyodideLockfileUrl", "pypiIndexUrl"])(
|
|
35
|
+
"ignores malformed %s while preserving valid overrides",
|
|
36
|
+
(key) => {
|
|
37
|
+
document.head.innerHTML = `
|
|
38
|
+
<base href="https://example.com/notebook/">
|
|
39
|
+
<marimo-wasm
|
|
40
|
+
data-pyodide-index-url="./pyodide/"
|
|
41
|
+
data-pyodide-lockfile-url="./lockfile/pyodide.json"
|
|
42
|
+
data-pypi-index-url="./packages/{package_name}.json"
|
|
43
|
+
></marimo-wasm>`;
|
|
44
|
+
const element = document.querySelector<HTMLElement>("marimo-wasm");
|
|
45
|
+
assert(element);
|
|
46
|
+
element.dataset[key] = "https://invalid host/";
|
|
47
|
+
|
|
48
|
+
expect(getWasmRuntimeConfig()).toEqual({
|
|
49
|
+
pyodideIndexUrl: "https://example.com/notebook/pyodide/",
|
|
50
|
+
pyodideLockfileUrl:
|
|
51
|
+
"https://example.com/notebook/lockfile/pyodide.json",
|
|
52
|
+
pypiIndexUrl:
|
|
53
|
+
"https://example.com/notebook/packages/{package_name}.json",
|
|
54
|
+
[key]: undefined,
|
|
55
|
+
});
|
|
56
|
+
},
|
|
57
|
+
);
|
|
58
|
+
});
|
package/src/core/wasm/bridge.ts
CHANGED
|
@@ -42,6 +42,7 @@ import { BasicTransport } from "../websocket/transports/basic";
|
|
|
42
42
|
import type { IConnectionTransport } from "../websocket/transports/transport";
|
|
43
43
|
import { PyodideRouter } from "./router";
|
|
44
44
|
import { getWorkerRPC } from "./rpc";
|
|
45
|
+
import { getWasmRuntimeConfig } from "./runtime-config";
|
|
45
46
|
import { createShareableLink } from "./share";
|
|
46
47
|
import { wasmInitStateAtom } from "./state";
|
|
47
48
|
import { fallbackFileStore, notebookFileStore } from "./store";
|
|
@@ -84,6 +85,8 @@ export class PyodideBridge implements RunRequests, EditRequests {
|
|
|
84
85
|
};
|
|
85
86
|
}
|
|
86
87
|
|
|
88
|
+
const runtimeConfig = getWasmRuntimeConfig();
|
|
89
|
+
|
|
87
90
|
// Create save worker
|
|
88
91
|
const saveWorker = createModuleWorker(
|
|
89
92
|
new URL(saveWorkerUrl, import.meta.url),
|
|
@@ -93,7 +96,9 @@ export class PyodideBridge implements RunRequests, EditRequests {
|
|
|
93
96
|
},
|
|
94
97
|
);
|
|
95
98
|
|
|
96
|
-
|
|
99
|
+
const rpc = getWorkerRPC<SaveWorkerSchema>(saveWorker);
|
|
100
|
+
rpc.send.bootstrap(runtimeConfig);
|
|
101
|
+
return rpc.proxy.request;
|
|
97
102
|
}
|
|
98
103
|
|
|
99
104
|
private constructor() {
|
|
@@ -101,6 +106,8 @@ export class PyodideBridge implements RunRequests, EditRequests {
|
|
|
101
106
|
return;
|
|
102
107
|
}
|
|
103
108
|
|
|
109
|
+
const runtimeConfig = getWasmRuntimeConfig();
|
|
110
|
+
|
|
104
111
|
// Create a worker
|
|
105
112
|
const worker = createModuleWorker(new URL(workerUrl, import.meta.url), {
|
|
106
113
|
// Pass the version (and optional capability suffix) to the worker
|
|
@@ -109,6 +116,7 @@ export class PyodideBridge implements RunRequests, EditRequests {
|
|
|
109
116
|
|
|
110
117
|
// Create the RPC
|
|
111
118
|
this.rpc = getWorkerRPC<WorkerSchema>(worker);
|
|
119
|
+
this.rpc.send.bootstrap(runtimeConfig);
|
|
112
120
|
|
|
113
121
|
// Listeners
|
|
114
122
|
this.rpc.addMessageListener("ready", () => {
|
package/src/core/wasm/rpc.ts
CHANGED
|
@@ -6,11 +6,13 @@ import {
|
|
|
6
6
|
type RPCSchema,
|
|
7
7
|
} from "rpc-anywhere";
|
|
8
8
|
import { Logger } from "@/utils/Logger";
|
|
9
|
+
import type { WasmRuntimeConfig } from "./runtime-config";
|
|
9
10
|
import { TRANSPORT_ID } from "./worker/constants";
|
|
10
11
|
|
|
11
12
|
export type ParentSchema = RPCSchema<{
|
|
12
13
|
messages: {
|
|
13
14
|
consumerReady: {};
|
|
15
|
+
bootstrap: WasmRuntimeConfig;
|
|
14
16
|
};
|
|
15
17
|
}>;
|
|
16
18
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
export interface WasmRuntimeConfig {
|
|
4
|
+
pyodideIndexUrl?: string;
|
|
5
|
+
pyodideLockfileUrl?: string;
|
|
6
|
+
pypiIndexUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function getWasmRuntimeConfig(): WasmRuntimeConfig {
|
|
10
|
+
const element = document.querySelector<HTMLElement>("marimo-wasm");
|
|
11
|
+
const resolve = (url: string | undefined) => {
|
|
12
|
+
try {
|
|
13
|
+
return url ? new URL(url, document.baseURI).href : undefined;
|
|
14
|
+
} catch {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
pyodideIndexUrl: resolve(element?.dataset.pyodideIndexUrl),
|
|
20
|
+
pyodideLockfileUrl: resolve(element?.dataset.pyodideLockfileUrl),
|
|
21
|
+
// URL serialization escapes the placeholder understood by micropip.
|
|
22
|
+
pypiIndexUrl: resolve(element?.dataset.pypiIndexUrl)?.replaceAll(
|
|
23
|
+
"%7Bpackage_name%7D",
|
|
24
|
+
"{package_name}",
|
|
25
|
+
),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -41,10 +41,9 @@ export class DefaultWasmController implements WasmController {
|
|
|
41
41
|
return this.pyodide;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
async bootstrap(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}): Promise<PyodideInterface> {
|
|
44
|
+
async bootstrap(
|
|
45
|
+
opts: Parameters<WasmController["bootstrap"]>[0],
|
|
46
|
+
): Promise<PyodideInterface> {
|
|
48
47
|
const pyodide = await this.loadPyodideAndPackages(opts);
|
|
49
48
|
|
|
50
49
|
if (MAKE_SNAPSHOT) {
|
|
@@ -55,10 +54,9 @@ export class DefaultWasmController implements WasmController {
|
|
|
55
54
|
return pyodide;
|
|
56
55
|
}
|
|
57
56
|
|
|
58
|
-
private async loadPyodideAndPackages(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}): Promise<PyodideInterface> {
|
|
57
|
+
private async loadPyodideAndPackages(
|
|
58
|
+
opts: Parameters<WasmController["bootstrap"]>[0],
|
|
59
|
+
): Promise<PyodideInterface> {
|
|
62
60
|
if (!loadPyodide) {
|
|
63
61
|
throw new Error("loadPyodide is not defined");
|
|
64
62
|
}
|
|
@@ -68,7 +66,9 @@ export class DefaultWasmController implements WasmController {
|
|
|
68
66
|
// Without this, this fails in Firefox with
|
|
69
67
|
// `Could not extract indexURL path from pyodide module`
|
|
70
68
|
// This fixes for Firefox and does not break Chrome/others
|
|
71
|
-
const indexURL =
|
|
69
|
+
const indexURL =
|
|
70
|
+
opts.pyodideIndexUrl ??
|
|
71
|
+
`https://cdn.jsdelivr.net/pyodide/${opts.pyodideVersion}/full/`;
|
|
72
72
|
const pyodide = await loadPyodide({
|
|
73
73
|
// Perf: These get loaded while pyodide is being bootstrapped
|
|
74
74
|
packages: [
|
|
@@ -81,16 +81,26 @@ export class DefaultWasmController implements WasmController {
|
|
|
81
81
|
"packaging",
|
|
82
82
|
],
|
|
83
83
|
_makeSnapshot: MAKE_SNAPSHOT,
|
|
84
|
-
lockFileURL:
|
|
84
|
+
lockFileURL:
|
|
85
|
+
opts.pyodideLockfileUrl ??
|
|
86
|
+
`https://wasm.marimo.app/pyodide-lock.json?v=${opts.version}&pyodide=${opts.pyodideVersion}`,
|
|
85
87
|
indexURL,
|
|
86
88
|
// Since Pyodide 0.28.0, when lockFileURL is set, the package base URL
|
|
87
89
|
// defaults to the lockfile's URL (wasm.marimo.app) instead of indexURL.
|
|
88
90
|
// Unlike Node, browsers get no CDN fallback on a failed fetch, so we
|
|
89
|
-
// should pin packageBaseUrl
|
|
91
|
+
// should pin packageBaseUrl to indexURL to restore
|
|
90
92
|
// the resolution akin to pre-0.28.
|
|
91
93
|
packageBaseUrl: indexURL,
|
|
92
94
|
convertNullToNone: true,
|
|
93
95
|
});
|
|
96
|
+
if (opts.pypiIndexUrl) {
|
|
97
|
+
const micropip = pyodide.pyimport("micropip");
|
|
98
|
+
try {
|
|
99
|
+
micropip.set_index_urls(opts.pypiIndexUrl);
|
|
100
|
+
} finally {
|
|
101
|
+
micropip.destroy();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
94
104
|
this.pyodide = pyodide;
|
|
95
105
|
span.end("ok");
|
|
96
106
|
return pyodide;
|
|
@@ -9,9 +9,11 @@ import {
|
|
|
9
9
|
} from "rpc-anywhere";
|
|
10
10
|
import type { SaveNotebookRequest } from "@/core/network/types";
|
|
11
11
|
import { decodeUtf8 } from "@/utils/strings";
|
|
12
|
+
import { Deferred } from "../../../utils/Deferred";
|
|
12
13
|
import { prettyError } from "../../../utils/errors";
|
|
13
14
|
import { Logger } from "../../../utils/Logger";
|
|
14
15
|
import type { ParentSchema } from "../rpc";
|
|
16
|
+
import type { WasmRuntimeConfig } from "../runtime-config";
|
|
15
17
|
import { TRANSPORT_ID } from "./constants";
|
|
16
18
|
import { WasmFileSystem } from "./fs";
|
|
17
19
|
import { getController } from "./getController";
|
|
@@ -25,6 +27,8 @@ declare const self: Window & {
|
|
|
25
27
|
pyodide: PyodideInterface;
|
|
26
28
|
};
|
|
27
29
|
|
|
30
|
+
const runtimeConfig = new Deferred<WasmRuntimeConfig>();
|
|
31
|
+
|
|
28
32
|
// Initialize
|
|
29
33
|
async function loadPyodideAndPackages() {
|
|
30
34
|
try {
|
|
@@ -36,6 +40,7 @@ async function loadPyodideAndPackages() {
|
|
|
36
40
|
const controller = await getController(marimoVersion);
|
|
37
41
|
self.controller = controller;
|
|
38
42
|
self.pyodide = await controller.bootstrap({
|
|
43
|
+
...(await runtimeConfig.promise),
|
|
39
44
|
version: marimoVersion,
|
|
40
45
|
pyodideVersion: pyodideVersion,
|
|
41
46
|
});
|
|
@@ -100,6 +105,8 @@ const rpc = createRPC<SaveWorkerSchema, ParentSchema>({
|
|
|
100
105
|
requestHandler,
|
|
101
106
|
});
|
|
102
107
|
|
|
108
|
+
rpc.addMessageListener("bootstrap", (config) => runtimeConfig.resolve(config));
|
|
109
|
+
|
|
103
110
|
rpc.send("ready", {});
|
|
104
111
|
|
|
105
112
|
function getMarimoVersion() {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
import type { PyodideInterface } from "pyodide";
|
|
3
|
+
import type { WasmRuntimeConfig } from "../runtime-config";
|
|
3
4
|
import type { UserConfig } from "@/core/config/config-schema";
|
|
4
5
|
import type {
|
|
5
6
|
CommandMessage,
|
|
@@ -43,10 +44,12 @@ export interface WasmController {
|
|
|
43
44
|
* Prepare the wasm environment
|
|
44
45
|
* @param opts.version - The marimo version
|
|
45
46
|
*/
|
|
46
|
-
bootstrap(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
bootstrap(
|
|
48
|
+
opts: WasmRuntimeConfig & {
|
|
49
|
+
version: string;
|
|
50
|
+
pyodideVersion: string;
|
|
51
|
+
},
|
|
52
|
+
): Promise<PyodideInterface>;
|
|
50
53
|
/**
|
|
51
54
|
* Mount the filesystem
|
|
52
55
|
* @param opts.code - The code to mount
|
|
@@ -22,6 +22,7 @@ import { prettyError } from "../../../utils/errors";
|
|
|
22
22
|
import { invariant } from "../../../utils/invariant";
|
|
23
23
|
import { Logger } from "../../../utils/Logger";
|
|
24
24
|
import type { ParentSchema } from "../rpc";
|
|
25
|
+
import type { WasmRuntimeConfig } from "../runtime-config";
|
|
25
26
|
import { TRANSPORT_ID } from "./constants";
|
|
26
27
|
import { WasmFileSystem } from "./fs";
|
|
27
28
|
import { getController } from "./getController";
|
|
@@ -47,6 +48,8 @@ declare const self: Window & {
|
|
|
47
48
|
|
|
48
49
|
const workerInitSpan = t.startSpan("worker:init");
|
|
49
50
|
|
|
51
|
+
const runtimeConfig = new Deferred<WasmRuntimeConfig>();
|
|
52
|
+
|
|
50
53
|
// Initialize pyodide
|
|
51
54
|
async function loadPyodideAndPackages() {
|
|
52
55
|
try {
|
|
@@ -58,6 +61,7 @@ async function loadPyodideAndPackages() {
|
|
|
58
61
|
message: "Loading marimo...",
|
|
59
62
|
});
|
|
60
63
|
self.pyodide = await t.wrapAsync(controller.bootstrap.bind(controller))({
|
|
64
|
+
...(await runtimeConfig.promise),
|
|
61
65
|
version: marimoVersion,
|
|
62
66
|
pyodideVersion: pyodideVersion,
|
|
63
67
|
});
|
|
@@ -354,6 +358,8 @@ const rpc = createRPC<WorkerSchema, ParentSchema>({
|
|
|
354
358
|
requestHandler,
|
|
355
359
|
});
|
|
356
360
|
|
|
361
|
+
rpc.addMessageListener("bootstrap", (config) => runtimeConfig.resolve(config));
|
|
362
|
+
|
|
357
363
|
rpc.send("ready", {});
|
|
358
364
|
|
|
359
365
|
/// Listeners
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./worker-k3VMDfLg.js";var t=e(((e,t)=>{t.exports={}}));export default t();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./save-worker-Di2CE_lj.js";var t=e(((e,t)=>{t.exports={}}));export default t();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{Ka as e}from"./index-BnWsVdKv.js";var t=Object.prototype.hasOwnProperty;function n(e,n){return e!=null&&t.call(e,n)}function r(t,r){return t!=null&&e(t,r,n)}export{r as t};
|