@marimo-team/islands 0.23.2-dev55 → 0.23.2-dev58

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/main.js CHANGED
@@ -45525,7 +45525,7 @@ ${c}
45525
45525
  return Logger.warn("Failed to get version from mount config"), null;
45526
45526
  }
45527
45527
  }
45528
- const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.2-dev55"), showCodeInRunModeAtom = atom(true);
45528
+ const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.2-dev58"), showCodeInRunModeAtom = atom(true);
45529
45529
  atom(null);
45530
45530
  var VIRTUAL_FILE_REGEX = /\/@file\/([^\s"&'/]+)\.([\dA-Za-z]+)/g, VirtualFileTracker = class e {
45531
45531
  constructor() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.23.2-dev55",
3
+ "version": "0.23.2-dev58",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -0,0 +1,113 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
4
+
5
+ const { mockNotebookReadFile, rpcListeners } = vi.hoisted(() => ({
6
+ mockNotebookReadFile: vi.fn(),
7
+ rpcListeners: {} as Record<string, () => void>,
8
+ }));
9
+
10
+ // Mock browser globals before any imports
11
+ vi.stubGlobal("crossOriginIsolated", false);
12
+ vi.stubGlobal(
13
+ "Worker",
14
+ vi.fn(() => ({
15
+ addEventListener: vi.fn(),
16
+ postMessage: vi.fn(),
17
+ terminate: vi.fn(),
18
+ })),
19
+ );
20
+
21
+ class MockURL extends URL {
22
+ static override createObjectURL = vi.fn(() => "blob:mock-url");
23
+ static override revokeObjectURL = vi.fn();
24
+ }
25
+ vi.stubGlobal("URL", MockURL);
26
+
27
+ vi.mock("@/core/wasm/rpc", () => ({
28
+ getWorkerRPC: () => ({
29
+ proxy: {
30
+ request: {
31
+ bridge: vi.fn(),
32
+ startSession: vi.fn(),
33
+ readFile: vi.fn(),
34
+ readNotebook: vi.fn(),
35
+ saveNotebook: vi.fn(),
36
+ },
37
+ send: { consumerReady: vi.fn() },
38
+ },
39
+ addMessageListener: (event: string, cb: () => void) => {
40
+ rpcListeners[event] = cb;
41
+ },
42
+ }),
43
+ }));
44
+
45
+ vi.mock("@/core/meta/globals", () => ({
46
+ getMarimoVersion: () => "0.0.0-test",
47
+ }));
48
+
49
+ vi.mock("@/core/wasm/utils", () => ({
50
+ isWasm: () => true,
51
+ }));
52
+
53
+ vi.mock("@/core/wasm/store", () => ({
54
+ fallbackFileStore: { readFile: vi.fn(), saveFile: vi.fn() },
55
+ notebookFileStore: { readFile: mockNotebookReadFile, saveFile: vi.fn() },
56
+ }));
57
+
58
+ // Import after all mocks are set up
59
+ import { store } from "@/core/state/jotai";
60
+ import { initialModeAtom } from "@/core/mode";
61
+ import { PyodideBridge } from "../bridge";
62
+
63
+ // Access INSTANCE once at module level so the constructor runs (and
64
+ // addMessageListener populates rpcListeners) before any test executes.
65
+ void PyodideBridge.INSTANCE;
66
+
67
+ describe("PyodideBridge.readCode", () => {
68
+ beforeEach(() => {
69
+ vi.clearAllMocks();
70
+ });
71
+
72
+ afterEach(() => {
73
+ store.set(initialModeAtom, undefined);
74
+ });
75
+
76
+ it("reads from notebookFileStore in read mode", async () => {
77
+ store.set(initialModeAtom, "read");
78
+ // Trigger getSaveWorker — it reads the current mode and returns a stub
79
+ // whose readNotebook delegates to notebookFileStore.
80
+ rpcListeners.initialized();
81
+ mockNotebookReadFile.mockResolvedValue(
82
+ "import numpy as np\nprint(np.__version__)",
83
+ );
84
+
85
+ const result = await PyodideBridge.INSTANCE.readCode();
86
+
87
+ expect(result).toEqual({
88
+ contents: "import numpy as np\nprint(np.__version__)",
89
+ });
90
+ expect(mockNotebookReadFile).toHaveBeenCalledTimes(1);
91
+ });
92
+
93
+ it("returns empty string when notebookFileStore has no code in read mode", async () => {
94
+ store.set(initialModeAtom, "read");
95
+ rpcListeners.initialized();
96
+ mockNotebookReadFile.mockResolvedValue(null);
97
+
98
+ const result = await PyodideBridge.INSTANCE.readCode();
99
+
100
+ expect(result).toEqual({ contents: "" });
101
+ });
102
+
103
+ it("does not call notebookFileStore in edit mode", async () => {
104
+ store.set(initialModeAtom, "edit");
105
+ // getSaveWorker in edit mode creates a real worker (mocked); readNotebook
106
+ // goes to the RPC proxy, not notebookFileStore.
107
+ rpcListeners.initialized();
108
+
109
+ await PyodideBridge.INSTANCE.readCode();
110
+
111
+ expect(mockNotebookReadFile).not.toHaveBeenCalled();
112
+ });
113
+ });
@@ -67,10 +67,10 @@ export class PyodideBridge implements RunRequests, EditRequests {
67
67
 
68
68
  private getSaveWorker(): SaveWorker {
69
69
  if (getInitialAppMode() === "read") {
70
- Logger.debug("Skipping SaveWorker in read-mode");
70
+ Logger.debug("Using partially disabled SaveWorker in read-mode");
71
71
  return {
72
72
  readFile: throwNotImplemented,
73
- readNotebook: throwNotImplemented,
73
+ readNotebook: async () => (await notebookFileStore.readFile()) ?? "",
74
74
  saveNotebook: throwNotImplemented,
75
75
  };
76
76
  }