Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

CommandBar.showForm never settles if an HTML view invokes a plugin command

Đang mở
#790 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
45/100
Loại issue
Lỗi
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
javascript
Lĩnh vực
developer-experience

Hướng nghiên cứu

Start by reading np.Shared/requiredFiles/pluginToHTMLCommsBridge.js and tracing how DataStore.invokePluginCommandByName interacts with pending CommandBar.showForm calls. Reproduce with the Dashboard timer running while /convert to project awaits the form. Done means HTML view commands no longer leave the form promise pending: calls are queued until dismissal or the form settles if preempted.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

API bug

Summary

CommandBar.showForm() never settles if an HTML view invokes another plugin command while the form is open. The original command stays suspended, the note is not updated, and there is no error. Closing the HTML window avoids the problem because nothing then calls back into the plugin.

Seen on NotePlan 3.22 (build 1542), macOS, 26 Oct 2026.

Repro

  1. Open the Dashboard HTML window (jgclark.Dashboard, custom id jgclark.Dashboard.main) and leave it open. With the Time Block section enabled, the page runs setInterval every 54 seconds.
  2. Open a normal note and run the Projects command /convert to project (jgclark.Reviews / convertToProject).
  3. That command reaches await CommandBar.showForm(...) and stops. The form does not complete, and the command logs nothing further. Run it again and the same thing happens.
  4. Close Dashboard and run the same command. The form appears, Submit writes the note frontmatter, and the command logs success.

What the plugin is doing

After a couple of checks and getReviewSettings(), the command does only this:

const formResult = await CommandBar.showForm({
  title: `Convert '${title}' to a Project`,
  submitText: 'Convert',
  fields,
})

Every path after that await logs either cancellation, invalid data, a write failure, or success, and the catch logs exceptions. None of those lines appear on the failed runs. The promise from showForm is neither resolved nor rejected.

The same form succeeds when Dashboard is closed, so the field list is not the cause.

What the logs show

Plugin console for a failed run (16:08:32), with nothing after the settings line:

--- 2026-10-26T16:08:32Z 'convert to project' (jgclark.Reviews) ---
Executing function 'convertToProject'
INFO  convertToProject :: Starting for note 'Live Translation for services' (...)
INFO  getReviewSettings :: Will use Perspective 'Home', and its folder & teamspace settings

One second later, Dashboard runs because the webview posted a bridge message:

[WebView] bridge::runPluginCommand JS file in np.Shared Sending command "onMessageFromHTMLView" to NotePlan: "jgclark.Dashboard"
--- 2026-10-26T16:08:33Z 'onMessageFromHTMLView' (jgclark.Dashboard) ---
Executing function 'onMessageFromHTMLView'
INFO  bridgeClickDashboardItem: refreshSomeSections

That refreshSomeSections call is the Time Block timer. It fires about every 54 seconds for as long as the Dashboard window is visible (16:02:37, 16:03:31, 16:04:25, 16:05:20, 16:06:44, 16:07:39, 16:08:33, 16:09:28, ...). Each failed /convert to project was still awaiting showForm when the next tick arrived (16:02:11 then refresh at 16:02:37; 16:03:28 then 16:03:31; 16:08:32 then 16:08:33). None of those awaits ever resumed.

The run that succeeded (16:10:49, frontmatter written at 16:10:57) fell in a gap between those ticks. The same command also succeeds whenever Dashboard is closed, so the timer never posts.

The bridge code in np.Shared/requiredFiles/pluginToHTMLCommsBridge.js is:

const code = '(async function() { await DataStore.invokePluginCommandByName("onMessageFromHTMLView", "jgclark.Dashboard", [type, data]);})()'
window.webkit.messageHandlers.jsBridge.postMessage({ code, onHandle: '', id: '1' })

So while jgclark.Reviews is suspended inside CommandBar.showForm, the webview starts a second plugin command, jgclark.Dashboard.onMessageFromHTMLView, via DataStore.invokePluginCommandByName.

What appears to go wrong in the app

showForm is waiting on the command bar. A jsBridge message then starts another plugin command on the same JavaScript context. That second command runs (refreshSomeSections does its work and returns). The first command's showForm promise is left pending: the form is gone or never committed, and no completion handler runs. The first command cannot log, write, or show an error.

This matches a modal UI promise that is dropped when a new plugin command begins, instead of being resolved with submitted: false or rejected.

The same hole would affect any await CommandBar.showForm / prompt / textPrompt while any HTML view posts invokePluginCommandByName. Dashboard's idle refresh (refreshEnabledSections) and windowResized on hide use that same bridge, so they can trip it too. The 54-second Time Block timer is the one that lined up with these logs.

Expected behavior

While a command-bar form is open, invokePluginCommandByName coming from an HTML view should be queued until the form is dismissed. If a new command must preempt the form, showForm should still settle (submitted: false, or a rejection) so the caller's await resumes. A background refresh must not swallow the form and leave the original command hung.

Ngôn ngữ chính
JavaScript
Star
203
Fork
81
Merge trung bình
52 phút
Pull request đã merge (30 ngày)
1

Chuẩn bị môi trường

Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của NotePlan/plugins

Tất cả issue của NotePlan/plugins

Issue tương tự

Thêm issue về JavaScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.