@marimo-team/islands 0.25.3-dev20 → 0.25.3-dev23

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 (91) hide show
  1. package/dist/{ConnectedDataExplorerComponent-CNMliVzw.js → ConnectedDataExplorerComponent-DfG3PRaJ.js} +9 -9
  2. package/dist/{ErrorBoundary-DAPIRYqd.js → ErrorBoundary-h0Ea26dF.js} +8 -8
  3. package/dist/{abnfDiagram-VCTEODGH-D-Ez91gV.js → abnfDiagram-VCTEODGH-B3w-XWX8.js} +2 -2
  4. package/dist/{any-language-editor-DZ_YTVus.js → any-language-editor-D4q-IFcM.js} +2 -2
  5. package/dist/{architectureDiagram-5GKGNRK7-CTpcNtO8.js → architectureDiagram-5GKGNRK7-C18U9A6k.js} +1 -1
  6. package/dist/{chat-ui-DaHynk8g.js → chat-ui-w8SVynkn.js} +1096 -1096
  7. package/dist/{check-EDwSwP89.js → check-BMKBBrdc.js} +1 -1
  8. package/dist/{chunk-IMKFNOWR-DGxi-zeo.js → chunk-IMKFNOWR-CrS5bzqW.js} +1 -1
  9. package/dist/{chunk-SHT3W25Y-CV9J3rAB.js → chunk-SHT3W25Y-StpvPvUG.js} +1 -1
  10. package/dist/{chunk-SVP7TREG-BL-9Fqgg.js → chunk-SVP7TREG-CBXjbYZC.js} +1 -1
  11. package/dist/{chunk-TICWLB2K-Cu_XMjDM.js → chunk-TICWLB2K-Dp6bIb-q.js} +1 -1
  12. package/dist/{classDiagram-ZZMXUADV-BXXV13Hq.js → classDiagram-ZZMXUADV-BFYuxV5g.js} +2 -2
  13. package/dist/{classDiagram-v2-VYDZK3BY-B7FXJ1Cp.js → classDiagram-v2-VYDZK3BY-D_tjXVMl.js} +2 -2
  14. package/dist/{code-visibility-DkCqn-PO.js → code-visibility-vqPDeo1_.js} +5 -5
  15. package/dist/{common-DsUPhkD6.js → common-DNPxRLm_.js} +6265 -6262
  16. package/dist/{copy-icon-Ft7t9bqz.js → copy-icon-BgUO8jsi.js} +2 -2
  17. package/dist/{cynefinDiagram-5FMLGOSQ-CH96rwba.js → cynefinDiagram-5FMLGOSQ-DSgYrHB2.js} +1 -1
  18. package/dist/{dagre-GXQ25YYZ-BD3PmpFY.js → dagre-GXQ25YYZ-GYlruCBf.js} +1 -1
  19. package/dist/{data-grid-overlay-editor-D7UuVsgB.js → data-grid-overlay-editor-B9QxYH-I.js} +1 -1
  20. package/dist/{diagram-S7CK7UJ4-BsSJJldB.js → diagram-S7CK7UJ4-DRu5LX5_.js} +1 -1
  21. package/dist/{diagram-UQ7AKVKN-muQtNZc4.js → diagram-UQ7AKVKN-DD7uiejP.js} +1 -1
  22. package/dist/{diagram-VX7I27RA-CdhuZAqR.js → diagram-VX7I27RA-ByH9KAJJ.js} +1 -1
  23. package/dist/{diagram-Z3DM3KII-BD8mXjOj.js → diagram-Z3DM3KII-BsQHPRke.js} +1 -1
  24. package/dist/{dialog-CEBFZNyc.js → dialog-Cc479ZEH.js} +24 -24
  25. package/dist/{dropdown-menu-CP_qCYHC.js → dropdown-menu-DHP9P4VE.js} +790 -790
  26. package/dist/{ebnfDiagram-PWID7BFC-BIN1sweE.js → ebnfDiagram-PWID7BFC-CQRK5_eT.js} +2 -2
  27. package/dist/{erDiagram-RLTQ6QDP-Ctp5cfoN.js → erDiagram-RLTQ6QDP-BKtWrDVh.js} +1 -1
  28. package/dist/{error-banner-D-WCIiMt.js → error-banner-CFPHFw4h.js} +16 -16
  29. package/dist/{error-entries-Bv6bZPF3.js → error-entries-Damuuclv.js} +983 -985
  30. package/dist/{feedback-button-wnAMXOGA.js → feedback-button-BPcyKSZd.js} +28 -28
  31. package/dist/{flowDiagram-HODETNUW-3EfLrlFb.js → flowDiagram-HODETNUW-1IN-ih2E.js} +2 -2
  32. package/dist/{formats-27CW_UP4.js → formats-X4mMQWzX.js} +1 -1
  33. package/dist/{glide-data-editor-KvS90MGh.js → glide-data-editor-BIYjd9hQ.js} +10 -10
  34. package/dist/{glide-utils-DJyqh0EM.js → glide-utils-DM9zBO4W.js} +2 -2
  35. package/dist/{globals-yruoELTW.js → globals-BX22lYk2.js} +3 -3
  36. package/dist/{html-to-image-Bf8QMGi4.js → html-to-image-BdA59IUD.js} +60 -60
  37. package/dist/{infoDiagram-27XIBGKW-DipQoHxl.js → infoDiagram-27XIBGKW-CkB-zr4p.js} +1 -1
  38. package/dist/{ishikawaDiagram-5VMMS53U-DgFMjSGz.js → ishikawaDiagram-5VMMS53U-wlyLjBmM.js} +1 -1
  39. package/dist/{kanban-definition-UXKFOSKX-w1ACVjgl.js → kanban-definition-UXKFOSKX-C2usY0i-.js} +1 -1
  40. package/dist/{label-BDKF3Afc.js → label-DoysmLMW.js} +1 -1
  41. package/dist/main.js +722 -723
  42. package/dist/{mermaid-CHo49Yv-.js → mermaid-BA-Z6wGL.js} +35 -35
  43. package/dist/{mindmap-definition-YA3MSWOX-CrT0KSfX.js → mindmap-definition-YA3MSWOX-nKOWS8RR.js} +1 -1
  44. package/dist/{number-overlay-editor-R2i0FdxV.js → number-overlay-editor-DK-HbLsV.js} +1 -1
  45. package/dist/{pegDiagram-XKGWAZYB-BqvywNJA.js → pegDiagram-XKGWAZYB-Dac9EIKD.js} +2 -2
  46. package/dist/{pieDiagram-E7YTZNPT-BfxJ_XCc.js → pieDiagram-E7YTZNPT-B7S-DsW_.js} +1 -1
  47. package/dist/{process-output-BZg56CCb.js → process-output-CTPTtxXB.js} +4 -4
  48. package/dist/{railroadDiagram-O6MQD6OU-8vFLVTPu.js → railroadDiagram-O6MQD6OU-Cfa5Q-hr.js} +2 -2
  49. package/dist/{requirementDiagram-BXWQKSXE-a_MxGvxe.js → requirementDiagram-BXWQKSXE-d8zXCJIk.js} +1 -1
  50. package/dist/{reveal-component-C42-YBfQ.js → reveal-component-Dl9ZugRb.js} +9 -9
  51. package/dist/{select-BButFi-d.js → select-DemoKT4G.js} +199 -199
  52. package/dist/{sequenceDiagram-WJ2MYXX4-CXFMnxGh.js → sequenceDiagram-WJ2MYXX4-b6pei3lJ.js} +1 -1
  53. package/dist/{spec-BwarBpUJ.js → spec-BJzgmvVa.js} +4 -4
  54. package/dist/{stateDiagram-D77RDMKH-DQeA_CwI.js → stateDiagram-D77RDMKH-Be-xSpaZ.js} +2 -2
  55. package/dist/{stateDiagram-v2-MP3YSRHH-BxxQucm1.js → stateDiagram-v2-MP3YSRHH-5Y-FxesJ.js} +2 -2
  56. package/dist/{swimlanes-42K2YHIH-Do6L-cYg.js → swimlanes-42K2YHIH-nRRl4NU0.js} +1 -1
  57. package/dist/{swimlanesDiagram-VR7AAH4N-DUzPvSVU.js → swimlanesDiagram-VR7AAH4N-BS79510V.js} +2 -2
  58. package/dist/{timeline-definition-24CTP7MA-D3c46WM5.js → timeline-definition-24CTP7MA-Cfzf8WPf.js} +1 -1
  59. package/dist/toDate-B5mIgxwZ.js +1185 -0
  60. package/dist/{toast-B9UMEi8u.js → toast-PkdZraM8.js} +221 -221
  61. package/dist/{tooltip-BO1REbqs.js → tooltip-CtBZ5q8p.js} +51 -51
  62. package/dist/{use-restore-focus-BEM7sFWl.js → use-restore-focus-CKjfFjLM.js} +1 -1
  63. package/dist/{useAsyncData-Deh5kszT.js → useAsyncData-BD534XmW.js} +1 -1
  64. package/dist/{useDateFormatter-D8XruNGG.js → useDateFormatter-DkajGwwd.js} +2 -2
  65. package/dist/{useDeepCompareMemoize-DXwzRINI.js → useDeepCompareMemoize-C72_RNsu.js} +1 -1
  66. package/dist/{useLifecycle-j7D9uD1o.js → useLifecycle-BGWzTwHK.js} +2 -2
  67. package/dist/{useTheme-CRnjkku0.js → useTheme-BhQvec43.js} +83 -83
  68. package/dist/{vega-component-BeF9dfyO.js → vega-component-DfcYgj-Y.js} +7 -7
  69. package/dist/{vennDiagram-4TSXK5OY-BSZD8JcZ.js → vennDiagram-4TSXK5OY-CeY6Z1xZ.js} +1 -1
  70. package/dist/{wardleyDiagram-VM6X3IG4-48cUWkfA.js → wardleyDiagram-VM6X3IG4-Cxs9NtVi.js} +1 -1
  71. package/dist/{xychartDiagram-S5SC5T6Z-CswYgYeu.js → xychartDiagram-S5SC5T6Z-DNWbvPK7.js} +1 -1
  72. package/package.json +1 -1
  73. package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +12 -18
  74. package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +12 -23
  75. package/src/core/attachments/state.ts +5 -8
  76. package/src/core/host/__tests__/attachments.test.ts +57 -0
  77. package/src/core/host/__tests__/notebook-client.test.ts +131 -1
  78. package/src/core/host/events.ts +1 -0
  79. package/src/core/host/notebook-client.ts +20 -2
  80. package/src/core/host/resources/attachments.ts +19 -0
  81. package/src/core/islands/__tests__/bootstrap.test.ts +0 -26
  82. package/src/core/islands/bootstrap.ts +0 -1
  83. package/src/core/runtime/__tests__/runtime.test.ts +1 -1
  84. package/src/core/runtime/runtime.ts +4 -3
  85. package/src/core/websocket/__tests__/useNotebookClient.hook.test.tsx +30 -0
  86. package/src/core/websocket/__tests__/useNotebookSession.hook.test.tsx +0 -171
  87. package/src/core/websocket/state.ts +7 -0
  88. package/src/core/websocket/useNotebookClient.ts +9 -1
  89. package/src/core/websocket/useNotebookSession.tsx +0 -8
  90. package/src/utils/once.ts +19 -19
  91. package/dist/toDate-UtiwmnH2.js +0 -705
@@ -41,11 +41,6 @@ import { Logger } from "@/utils/Logger";
41
41
  import { Deferred } from "@/utils/Deferred";
42
42
  import { cellId } from "@/__tests__/branded";
43
43
  import { alertAtom, getPackageAlert } from "@/core/alerts/state";
44
- import {
45
- type Attachment,
46
- attachmentsAtom,
47
- agentAttachmentsAtom,
48
- } from "@/core/attachments/state";
49
44
  import { notebookAtom } from "@/core/cells/cells";
50
45
  import { AppConfigSchema } from "@/core/config/config-schema";
51
46
  import { ConnectionNotice } from "@/components/editor/alerts/connection-notice";
@@ -239,28 +234,6 @@ describe("useNotebookSession messages", () => {
239
234
  });
240
235
  }
241
236
 
242
- it("replaces attachment snapshots, including the last detach", () => {
243
- const agent: Attachment = {
244
- id: "a1",
245
- kind: "agent",
246
- name: "Pi",
247
- since: "2026-10-14T00:00:00Z",
248
- notebook_id: "nb-test",
249
- identity: "pi-thread",
250
- };
251
- const client: Attachment = {
252
- id: "c1",
253
- kind: "client",
254
- name: null,
255
- since: "2026-10-14T00:00:01Z",
256
- notebook_id: "nb-test",
257
- };
258
- for (const attachments of [[agent, client], [client], []]) {
259
- receive({ data: { op: "attachments", attachments } });
260
- expect(store.get(attachmentsAtom)).toEqual(attachments);
261
- }
262
- });
263
-
264
237
  it.each(["{broken", "null"])(
265
238
  "reports a malformed legacy frame and continues applying notifications: %s",
266
239
  (data) => {
@@ -408,150 +381,6 @@ it.each(["kernel-ready", "reconnected"])(
408
381
  },
409
382
  );
410
383
 
411
- describe("attachment snapshots across browser connections", () => {
412
- const agent: Attachment = {
413
- id: "a1",
414
- kind: "agent",
415
- name: "Pi",
416
- since: "2026-10-14T00:00:00Z",
417
- notebook_id: "nb-test",
418
- identity: "pi-thread",
419
- };
420
-
421
- function connectedSession() {
422
- const store = createStore();
423
- store.set(connectionAtom, { state: ConnectionState.OPEN });
424
- store.set(attachmentsAtom, [agent]);
425
- const transport = makeTransport(WebSocket.OPEN);
426
- vi.mocked(createConnectionTransport).mockReturnValue(transport);
427
- vi.mocked(useRuntimeManager).mockReturnValue(makeRuntimeManager());
428
- renderConnectionHook(store);
429
- const options = getTransportHandlers();
430
- const receive = (data: NotificationPayload["data"]) =>
431
- act(() => {
432
- options.onMessage(
433
- new MessageEvent("message", {
434
- data: JSON.stringify({ op: data.op, data }),
435
- }),
436
- );
437
- });
438
- return { store, transport, options, receive };
439
- }
440
-
441
- it.each([
442
- "MARIMO_NO_FILE_KEY",
443
- "MARIMO_NO_SESSION_ID",
444
- "MARIMO_NO_SESSION",
445
- "MARIMO_SHUTDOWN",
446
- "MARIMO_KERNEL_STARTUP_ERROR",
447
- "MARIMO_UNAUTHORIZED",
448
- "MARIMO_KIOSK_NOT_ALLOWED",
449
- "MARIMO_TRANSPORT_EXHAUSTED",
450
- ])("clears cached attachments on %s", (reason) => {
451
- const { store, transport, options } = connectedSession();
452
- act(() => options.onClose(new CloseEvent("close", { reason })));
453
- expect(store.get(attachmentsAtom)).toEqual([]);
454
- expect(store.get(agentAttachmentsAtom)).toEqual([]);
455
- expect(store.get(connectionAtom).state).toBe(ConnectionState.CLOSED);
456
- expect(transport.reconnect).not.toHaveBeenCalled();
457
- });
458
-
459
- it("clears the snapshot on transport error", () => {
460
- const { store, options } = connectedSession();
461
- act(() => options.onError(new Event("error")));
462
- expect(store.get(attachmentsAtom)).toEqual([]);
463
- expect(store.get(agentAttachmentsAtom)).toEqual([]);
464
- });
465
-
466
- it("waits for a fresh snapshot after a transient reconnect", async () => {
467
- const { store, transport, options, receive } = connectedSession();
468
- act(() => options.onClose(new CloseEvent("close")));
469
- expect(store.get(attachmentsAtom)).toEqual([]);
470
- expect(store.get(connectionAtom).state).toBe(ConnectionState.CONNECTING);
471
- expect(transport.reconnect).toHaveBeenCalledOnce();
472
-
473
- await act(async () => options.onOpen(new Event("open")));
474
- receive({ op: "reconnected" });
475
- expect(store.get(connectionAtom).state).toBe(ConnectionState.OPEN);
476
- expect(store.get(agentAttachmentsAtom)).toEqual([]);
477
-
478
- const refreshed = { ...agent, id: "a2", name: "Codex" };
479
- receive({ op: "attachments", attachments: [refreshed] });
480
- expect(store.get(agentAttachmentsAtom)).toEqual([refreshed]);
481
- receive({ op: "attachments", attachments: [] });
482
- expect(store.get(agentAttachmentsAtom)).toEqual([]);
483
- });
484
-
485
- it("keeps a fresh snapshot hidden until the session is ready", async () => {
486
- const { store, options, receive } = connectedSession();
487
- act(() => options.onClose(new CloseEvent("close")));
488
- await act(async () => options.onOpen(new Event("open")));
489
- receive({ op: "attachments", attachments: [agent] });
490
- expect(store.get(attachmentsAtom)).toEqual([agent]);
491
- expect(store.get(agentAttachmentsAtom)).toEqual([]);
492
- receive({ op: "reconnected" });
493
- expect(store.get(agentAttachmentsAtom)).toEqual([agent]);
494
- });
495
-
496
- it("invalidates an old snapshot when a new transport opens", async () => {
497
- const { store, options } = connectedSession();
498
- await act(async () => options.onOpen(new Event("open")));
499
- expect(store.get(attachmentsAtom)).toEqual([]);
500
- expect(store.get(agentAttachmentsAtom)).toEqual([]);
501
- });
502
- });
503
-
504
- it.each([true, false])(
505
- "keeps attachments only when kernel-ready resumes the session: %s",
506
- (resumed) => {
507
- const store = createStore();
508
- const attachments: Attachment[] = [
509
- {
510
- id: "a1",
511
- kind: "agent",
512
- name: "Pi",
513
- since: "2026-10-14T00:00:00Z",
514
- notebook_id: "nb-test",
515
- identity: "pi-thread",
516
- },
517
- ];
518
- store.set(attachmentsAtom, attachments);
519
- vi.mocked(createConnectionTransport).mockReturnValue(
520
- makeTransport(WebSocket.OPEN),
521
- );
522
- vi.mocked(useRuntimeManager).mockReturnValue(makeRuntimeManager());
523
- renderConnectionHook(store);
524
- const options = getTransportHandlers();
525
- act(() =>
526
- options.onMessage(
527
- new MessageEvent("message", {
528
- data: JSON.stringify({
529
- op: "kernel-ready",
530
- data: {
531
- op: "kernel-ready",
532
- cell_ids: [],
533
- codes: [],
534
- names: [],
535
- configs: [],
536
- layout: null,
537
- resumed,
538
- ui_values: {},
539
- last_executed_code: {},
540
- last_execution_time: {},
541
- app_config: { width: "normal" },
542
- kiosk: false,
543
- capabilities: { terminal: false },
544
- auto_instantiated: true,
545
- consumer_capabilities: { edit: true, interact: true },
546
- },
547
- }),
548
- }),
549
- ),
550
- );
551
- expect(store.get(attachmentsAtom)).toEqual(resumed ? attachments : []);
552
- },
553
- );
554
-
555
384
  describe("connection notice", () => {
556
385
  beforeEach(() => vi.useFakeTimers());
557
386
  afterEach(() => vi.useRealTimers());
@@ -0,0 +1,7 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { atom } from "jotai";
4
+ import type { NotebookClient } from "../host/notebook-client";
5
+
6
+ /** The client owned by the mounted notebook session. */
7
+ export const notebookClientAtom = atom<NotebookClient | null>(null);
@@ -14,6 +14,7 @@ import {
14
14
  type NotebookConnection,
15
15
  } from "../host/notebook-client";
16
16
  import { classifyCloseEvent } from "./connection-state";
17
+ import { notebookClientAtom } from "./state";
17
18
  import {
18
19
  createConnectionTransport,
19
20
  type ConnectionTransportOptions,
@@ -41,6 +42,7 @@ export function useNotebookClient(options: Options): NotebookClient {
41
42
 
42
43
  useEffect(() => {
43
44
  const lifetime = new AbortController();
45
+ store.set(notebookClientAtom, controller.client);
44
46
  controller.connect({
45
47
  createTransport: (url) =>
46
48
  createConnectionTransport({
@@ -61,9 +63,15 @@ export function useNotebookClient(options: Options): NotebookClient {
61
63
  decodeJson: jsonParseWithSpecialChar,
62
64
  classifyClose: classifyCloseEvent,
63
65
  });
64
- return () => lifetime.abort();
66
+ return () => {
67
+ lifetime.abort();
68
+ if (store.get(notebookClientAtom) === controller.client) {
69
+ store.set(notebookClientAtom, null);
70
+ }
71
+ };
65
72
  }, [
66
73
  controller,
74
+ store,
67
75
  sessionId,
68
76
  isStatic,
69
77
  transportType,
@@ -5,7 +5,6 @@ import { useAtom, useAtomValue, useSetAtom, useStore } from "jotai";
5
5
  import { useLayoutEffect } from "react";
6
6
  import { useErrorBoundary } from "react-error-boundary";
7
7
  import { toast } from "@/components/ui/use-toast";
8
- import { attachmentsAtom } from "@/core/attachments/state";
9
8
  import { getNotebook, useCellActions } from "@/core/cells/cells";
10
9
  import { applyTransactionChanges } from "@/core/cells/document-changes";
11
10
  import { AUTOCOMPLETER } from "@/core/codemirror/completion/Autocompleter";
@@ -140,7 +139,6 @@ export function useNotebookSession(opts: {
140
139
  const transportType = useAtomValue(connectionTransportTypeAtom);
141
140
  const setCacheInfo = useSetAtom(cacheInfoAtom);
142
141
  const setKernelStartupError = useSetAtom(kernelStartupErrorAtom);
143
- const setAttachments = useSetAtom(attachmentsAtom);
144
142
  const {
145
143
  setNamespaces: setStorageNamespaces,
146
144
  filterFromVariables: filterStorageFromVariables,
@@ -148,9 +146,6 @@ export function useNotebookSession(opts: {
148
146
 
149
147
  const handleNotification = (msg: NotificationPayload) => {
150
148
  switch (msg.data.op) {
151
- case "attachments":
152
- setAttachments(msg.data.attachments);
153
- return;
154
149
  case "reload":
155
150
  reloadSafe();
156
151
  return;
@@ -185,7 +180,6 @@ export function useNotebookSession(opts: {
185
180
  existingCells,
186
181
  });
187
182
  if (!msg.data.resumed) {
188
- setAttachments([]);
189
183
  // A freshly started kernel may expose a different environment
190
184
  // (e.g. new env vars); re-run discovery instead of reusing stale
191
185
  // suggestions from the previous kernel instance.
@@ -452,7 +446,6 @@ export function useNotebookSession(opts: {
452
446
  if (status.state === ConnectionState.NOT_STARTED) {
453
447
  return;
454
448
  }
455
- setAttachments([]);
456
449
  if (status.state === ConnectionState.OPEN) {
457
450
  updateStartupProgress(null);
458
451
  return; // kernel-ready, not the socket, establishes session readiness.
@@ -487,7 +480,6 @@ export function useNotebookSession(opts: {
487
480
  notebook,
488
481
  store,
489
482
  setConnection,
490
- setAttachments,
491
483
  setKernelStartupError,
492
484
  updateStartupProgress,
493
485
  ]);
package/src/utils/once.ts CHANGED
@@ -2,36 +2,36 @@
2
2
 
3
3
  import { arrayShallowEquals } from "./arrays";
4
4
 
5
- // oxlint-disable-next-line typescript/no-explicit-any
6
- export function once<T extends (...args: any[]) => any>(fn: T): T {
7
- let result: ReturnType<T>;
5
+ export function once<F extends (...args: never[]) => unknown>(fn: F): F;
6
+ export function once<Args extends unknown[], Result, This>(
7
+ fn: (this: This, ...args: Args) => Result,
8
+ ): (this: This, ...args: Args) => Result {
9
+ let result: Result;
8
10
  let called = false;
9
- return function (
10
- this: ThisParameterType<T>,
11
- ...args: Parameters<T>
12
- ): ReturnType<T> {
11
+ return function (this: This, ...args: Args): Result {
13
12
  if (!called) {
14
13
  called = true;
15
- result = fn.apply(this, args) as ReturnType<T>;
14
+ result = fn.apply(this, args);
16
15
  }
17
16
  return result;
18
- } as T;
17
+ };
19
18
  }
20
19
 
21
- // oxlint-disable-next-line typescript/no-explicit-any
22
- export function memoizeLastValue<T extends (...args: any[]) => any>(fn: T): T {
23
- let result: ReturnType<T>;
24
- let lastArgs: Parameters<T> | undefined;
20
+ export function memoizeLastValue<F extends (...args: never[]) => unknown>(
21
+ fn: F,
22
+ ): F;
23
+ export function memoizeLastValue<Args extends unknown[], Result, This>(
24
+ fn: (this: This, ...args: Args) => Result,
25
+ ): (this: This, ...args: Args) => Result {
26
+ let result: Result;
27
+ let lastArgs: Args | undefined;
25
28
  let lastError: unknown;
26
29
  let hasError = false;
27
30
 
28
- return function (
29
- this: ThisParameterType<T>,
30
- ...args: Parameters<T>
31
- ): ReturnType<T> {
31
+ return function (this: This, ...args: Args): Result {
32
32
  if (lastArgs === undefined || !arrayShallowEquals(args, lastArgs)) {
33
33
  try {
34
- result = fn.apply(this, args) as ReturnType<T>;
34
+ result = fn.apply(this, args);
35
35
  hasError = false;
36
36
  lastError = undefined;
37
37
  } catch (error) {
@@ -45,5 +45,5 @@ export function memoizeLastValue<T extends (...args: any[]) => any>(fn: T): T {
45
45
  throw lastError;
46
46
  }
47
47
  return result;
48
- } as T;
48
+ };
49
49
  }