Skip to content

Conversation

@APshenkin
Copy link
Contributor

@APshenkin APshenkin commented Nov 10, 2025

Description

This PR refactors binding layer + provides new Transport abstraction that allow user to replace default transport with WebSockets, custom protocols, or any other transport mechanism.

Motivation:

  1. System bindings uses HTTP transport for both request and response, but services bindings utilize JS callbacks
  2. Some usage scenarios doesn't allow to use HTTP transport (e.g. running external page with https and access to bindings)
  3. There is proposal to move default transport to Websocket (this needs continues investigation to identify how provide security guarantees)

List of changes:

  1. Drops JS callbacks for bindings in HTTP transport. Now all responses are returned via http. Events still uses JS callbacks, as HTTP doesn't support bidirectional connect.
  2. Replace GET /wails/runtime with POST /wails/runtime to handle cases with large data ([V3] CORS Error When Sending Large Data from frontend to backend service #4428)
  3. Moved /wails/capabilities and /wails/flags under messageProcessor for object System to allow other transports handle those requests as well
  4. Inject all flags that were specified for the app in webview (previously only resizeHandleWidth and resizeHandleHeight for Windows were passed)
  5. Decouple logic of bindings transport from message processor.
  6. Introduce Transport interfaces, that allow to replace default HTTP transport for bindings handling

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

Fixes # (issue)
#4418
#4428
#1516
#4686

Type of change

Please select the option that is relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration using wails doctor.

  • Windows
  • macOS
  • Linux

If you checked Linux, please specify the distro and version.

Test Configuration

Please paste the output of wails doctor. If you are unable to run this command, please describe your environment in as much detail as possible.

 Wails (v3.0.0-dev)  Wails Doctor

# System

┌──────────────────────────────────────────────────┐
| Name          | MacOS                            |
| Version       | 26.0.1                           |
| ID            | 25A362                           |
| Branding      | MacOS 26.0.1                     |
| Platform      | darwin                           |
| Architecture  | arm64                            |
| Apple Silicon | true                             |
| CPU           | Apple M4 Max                     |
| CPU 1         | Apple M4 Max                     |
| CPU 2         | Apple M4 Max                     |
| GPU           | 40 cores, Metal Support: Metal 4 |
| Memory        | 128 GB                           |
└──────────────────────────────────────────────────┘

# Build Environment

┌─────────────────────────────────────────────────────────┐
| Wails CLI    | v3.0.0-dev                               |
| Go Version   | go1.24.0                                 |
| Revision     | 4a445ce218b58db4a16ee8fa84eac0d7c9a69932 |
| Modified     | false                                    |
| -buildmode   | exe                                      |
| -compiler    | gc                                       |
| CGO_CFLAGS   |                                          |
| CGO_CPPFLAGS |                                          |
| CGO_CXXFLAGS |                                          |
| CGO_ENABLED  | 1                                        |
| CGO_LDFLAGS  |                                          |
| GOARCH       | arm64                                    |
| GOARM64      | v8.0                                     |
| GOOS         | darwin                                   |
| vcs          | git                                      |
| vcs.modified | false                                    |
| vcs.revision | 4a445ce218b58db4a16ee8fa84eac0d7c9a69932 |
| vcs.time     | 2025-08-04T22:42:25Z                     |
└─────────────────────────────────────────────────────────┘

Checklist:

  • I have updated website/src/pages/changelog.mdx with details of this PR
  • My code follows the general coding style of this project
  • x ] I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Summary by CodeRabbit

  • New Features

    • Pluggable IPC transport architecture with a default HTTP transport and a WebSocket transport example (real-time, reconnect, queued requests).
    • Example app and generated bindings for a GreetService demonstrating Greet, Echo, Add and GetTime over WebSocket.
  • Documentation

    • Added a comprehensive guide showing how to implement and wire custom transports (incl. asset serving and frontend setup).

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 10, 2025

Walkthrough

This PR introduces a pluggable IPC transport architecture (Transport interfaces and HTTPTransport), a WebSocket transport example (backend + frontend), refactors MessageProcessor to a request-driven API (RuntimeRequest / Args), adds an errs package with codegen, and updates the runtime/runtime bindings to support custom transports via setTransport/getTransport.

Changes

Cohort / File(s) Summary
Dependency updates
v3/go.mod, v3/examples/*/go.mod, v3/tests/window-visibility-test/go.mod
Remove indirect github.com/pkg/errors v0.9.1, bump github.com/wailsapp/go-webview2 to v1.0.22 in examples/tests, and add direct github.com/gorilla/websocket v1.5.3 to v3/go.mod.
Transport interfaces & HTTP transport
v3/pkg/application/transport.go, v3/pkg/application/transport_http.go
Add Transport, AssetServerTransport, TransportHTTPHandler interfaces and a concrete HTTPTransport implementation (handler middleware, Start/Stop, request routing to MessageProcessor).
WebSocket transport example (server)
v3/examples/websocket-transport/transport_websocket.go, v3/examples/websocket-transport/main.go
New WebSocketTransport example (server-side transport, message/event formats, ServeAssets) and example main that starts the app with the WebSocket transport.
WebSocket transport example (service + assets)
v3/examples/websocket-transport/GreetService.go, v3/examples/websocket-transport/assets/*, v3/examples/websocket-transport/frontend/*, v3/examples/websocket-transport/README.md
Add GreetService (methods + background timer events), frontend assets: WebSocketTransport JS implementation, generated bindings (greetservice/index), example index.html, and README docs.
MessageProcessor → request-driven API
v3/pkg/application/messageprocessor.go, v3/pkg/application/messageprocessor_args.go, v3/pkg/application/messageprocessor_*.go
Replace HTTP-centric handlers with a RuntimeRequest-based flow: HandleRuntimeCallWithIDs(ctx, req) → (any, error). Add Args/MapArgs utilities; convert per-object handlers (window, system, events, dialogs, clipboard, call, browser, screens, contextmenu, application) to return (any, error) and use errs for errors.
Transport event IPC & event wiring
v3/pkg/application/transport_event_ipc.go, v3/pkg/application/event_manager.go, v3/pkg/application/application.go, v3/pkg/application/application_options.go
Add EventIPCTransport to dispatch events to windows; application startup now initializes and starts configured Transport, wires WailsEventListener if supported, and uses AssetServerTransport for serving assets; Options gains Transport field; remove previous inline runtime/capabilities/flags serving.
Runtime changes (desktop TS/JS)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts, v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts, v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts, v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts, v3/internal/assetserver/bundledassets/runtime.js
Add RuntimeTransport interface, setTransport/getTransport, expose clientId and objectNames, update runtimeCallWithID to use custom transport (fallback to HTTP POST), simplify calls/dialog handling (remove global callbacks), and update bundled runtime exports.
Runtime Core signature & flags
v3/internal/runtime/runtime.go, v3/internal/runtime/runtime_*.go, v3/pkg/application/webview_window_*.go
Change Core() → Core(flags map[string]any) and flow flags into runtime; remove package-level flags variables and update webview window startup calls to pass flags.
Removed callback-based window methods
v3/pkg/application/webview_window.go, v3/pkg/application/window.go
Remove CallError, CallResponse, DialogError, DialogResponse on WebviewWindow and drop the Callback interface from Window.
Errors package & generator
v3/pkg/errs/errors.go, v3/pkg/errs/error_functions.gen.go, v3/pkg/errs/utils.go, v3/pkg/errs/codegen/error_functions/main.go, v3/pkg/errs/README.md
Add errs package (ErrorType constants, WailsError interface), code-generated typed constructors/wrappers (New*/Wrap*/Is*/Has*), utilities (Is/Cause/Has), and a generator to produce error functions.
Removed QueryParams file
v3/pkg/application/messageprocessor_params.go
Delete previous QueryParams/Args types in favor of new Args handling in messageprocessor_args.go.
Bundled frontend bindings
v3/examples/websocket-transport/assets/bindings/*, v3/examples/websocket-transport/frontend/bindings/*
Add auto-generated JS modules (greetservice.js, index.js) exposing GreetService binding methods for the WebSocket transport.

Sequence Diagram(s)

sequenceDiagram
    participant FE as Frontend (bindings)
    participant RT as Runtime (setTransport)
    participant CT as Custom Transport (e.g., WebSocket)
    participant Srv as Server Transport (HTTP/WebSocket)
    participant MP as MessageProcessor

    Note over FE,MP: New flow using custom transport
    FE->>RT: Call(object, method, args)
    RT->>CT: transport.call(object, method, windowName, args)
    CT->>Srv: transmit request (WS/other)
    Srv->>MP: HandleRuntimeCallWithIDs(ctx, RuntimeRequest)
    MP-->>Srv: (result, error)
    Srv->>CT: send response
    CT-->>RT: resolve promise with result
    RT-->>FE: deliver result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas needing extra attention:

  • Transport integration into application startup and asset serving (application.go, transport interfaces, HTTPTransport).
  • MessageProcessor refactor correctness: RuntimeRequest construction, Args parsing, and all converted process*Method signatures.
  • Runtime/TS changes: setTransport/getTransport, runtimeCallWithID fallback behavior and header propagation (clientId, window name).
  • Error package correctness and generated functions: generator template, generated code consistency with usage sites.
  • WebSocket transport example: message format, pending request lifecycle, reconnection semantics, and event broadcasting.

Possibly related PRs

Suggested labels

Enhancement, bindings, go, size:XXL, Implemented in v3

Suggested reviewers

  • leaanthony
  • atterpac

Poem

🐰 A little rabbit codes with cheer,

Transport hops from far to near,
Messages travel, bindings sing,
Errors shaped by a gen'd ring,
Frontend and backend now appear. 🎉

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title '[V3] Refactor binding transport layer' accurately and clearly summarizes the main objective of the pull request—a comprehensive refactoring of the bindings transport layer to introduce Transport abstractions.
Description check ✅ Passed The description covers key changes, motivation, related issues, and test configuration. However, it does not include the required Changelog update, lacks some test platform coverage, and does not include final verification of all tests passing locally.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 116ec40 and fa62058.

📒 Files selected for processing (1)
  • docs/src/content/docs/guides/custom-transport.mdx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/src/content/docs/guides/custom-transport.mdx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added Documentation Improvements or additions to documentation Windows MacOS Linux v3-alpha runtime labels Nov 10, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 16

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts (1)

20-20: Remove unused dialogResponses Map.

The dialogResponses Map is declared, checked in generateID, and cleaned up in the dialog function's finally block, but is never populated. This makes all Map operations dead code:

  • Line 136: dialogResponses.has(result) always returns false
  • Line 151: dialogResponses.delete(id) is always a no-op

Given the transport layer refactoring described in the PR, this appears to be incomplete cleanup from removing the per-dialog resolver storage pattern.

Apply this diff to remove the unused Map and related operations:

 import {newRuntimeCaller, objectNames} from "./runtime.js";
 import { nanoid } from './nanoid.js';
 
 // setup
 window._wails = window._wails || {};
 
-type PromiseResolvers = Omit<PromiseWithResolvers<any>, "promise">;
-
 const call = newRuntimeCaller(objectNames.Dialog);
-const dialogResponses = new Map<string, PromiseResolvers>();
 function generateID(): string {
-    let result;
-    do {
-        result = nanoid();
-    } while (dialogResponses.has(result));
-    return result;
+    return nanoid();
 }
 function dialog(type: number, options: MessageDialogOptions | OpenFileDialogOptions | SaveFileDialogOptions = {}): Promise<any> {
     const id = generateID();
 
-    return call(type, Object.assign({ "dialog-id": id }, options)).finally(() => {
-      dialogResponses.delete(id)
-    });
+    return call(type, Object.assign({ "dialog-id": id }, options));
 }

Also applies to: 136-136, 147-153

v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts (1)

95-119: Cancellation no longer fires because running is never true

running stays false, so result.oncancelled always takes the request.then(cancel) path and never sends the immediate cancel request. The cancel only goes out after the call has already resolved, making cancellation ineffective. Flip running to true when the transport call starts and reset it once the promise settles.

-    let running = false;
+    let running = true;
@@
-    request.then((res) => {
-        callResponses.delete(id);
-        result.resolve(res)
-    }, (err) => {
-        callResponses.delete(id);
-        result.reject(err);
-    });
+    request.then((res) => {
+        running = false;
+        callResponses.delete(id);
+        result.resolve(res);
+    }, (err) => {
+        running = false;
+        callResponses.delete(id);
+        result.reject(err);
+    });
🧹 Nitpick comments (3)
v3/internal/runtime/runtime.go (1)

10-20: Consider logging JSON marshal errors.

The function silently ignores json.Marshal errors on line 13-16, which may make debugging difficult if flags fail to serialize. Consider logging the error to help diagnose configuration issues while still allowing initialization to proceed.

Apply this diff to add error logging:

 func Core(flags map[string]any) string {
 	flagsStr := ""
 	if len(flags) > 0 {
 		f, err := json.Marshal(flags)
-		if err == nil {
+		if err != nil {
+			// Log error but continue - don't block runtime initialization
+			fmt.Fprintf(os.Stderr, "Warning: failed to marshal flags: %v\n", err)
+		} else {
 			flagsStr += fmt.Sprintf("window._wails.flags=%s;", f)
 		}
 	}
 
 	return runtimeInit + flagsStr + invoke + environment
 }

Note: You'll need to import "os" as well.

v3/examples/websocket-transport/assets/index.html (1)

334-346: Consider optimizing connection status polling.

The connection status is polled every second with setInterval. For a production application, consider:

  1. Using WebSocket connection/disconnection events for immediate updates
  2. Reducing polling frequency to reduce CPU usage

For a demo/example, the current implementation is acceptable.

v3/examples/websocket-transport/GreetService.go (1)

42-50: Guard greetCount against concurrent calls
Service methods can be invoked concurrently when multiple frontend requests arrive, so greetCount++ will race and emit inconsistent counts. Please switch to atomic.Int64 (or protect it with a mutex) before emitting events.

-import "context"
-import "fmt"
-import "time"
+import (
+	"context"
+	"fmt"
+	"sync/atomic"
+	"time"
+)
 
 type GreetService struct {
-	greetCount int
+	greetCount atomic.Int64
 	app        *application.App
 }
 
 func (g *GreetService) Greet(name string) string {
-	g.greetCount++
-	result := fmt.Sprintf("Hello, %s! (Greeted %d times via WebSocket)", name, g.greetCount)
+	count := g.greetCount.Add(1)
+	result := fmt.Sprintf("Hello, %s! (Greeted %d times via WebSocket)", name, count)
 
 	if g.app != nil {
-		g.app.Event.Emit("greet:count", g.greetCount)
+		g.app.Event.Emit("greet:count", count)
 	}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e4e340 and 34cf6c2.

⛔ Files ignored due to path filters (8)
  • v3/examples/dev/go.sum is excluded by !**/*.sum
  • v3/examples/file-association/go.sum is excluded by !**/*.sum
  • v3/examples/gin-example/go.sum is excluded by !**/*.sum
  • v3/examples/gin-routing/go.sum is excluded by !**/*.sum
  • v3/examples/gin-service/go.sum is excluded by !**/*.sum
  • v3/examples/notifications/go.sum is excluded by !**/*.sum
  • v3/go.sum is excluded by !**/*.sum
  • v3/tests/window-visibility-test/go.sum is excluded by !**/*.sum
📒 Files selected for processing (58)
  • v3/examples/dev/go.mod (1 hunks)
  • v3/examples/file-association/go.mod (1 hunks)
  • v3/examples/gin-example/go.mod (1 hunks)
  • v3/examples/gin-routing/go.mod (1 hunks)
  • v3/examples/gin-service/go.mod (1 hunks)
  • v3/examples/notifications/go.mod (1 hunks)
  • v3/examples/websocket-transport/GreetService.go (1 hunks)
  • v3/examples/websocket-transport/README.md (1 hunks)
  • v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1 hunks)
  • v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js (1 hunks)
  • v3/examples/websocket-transport/assets/index.html (1 hunks)
  • v3/examples/websocket-transport/assets/websocket-transport.js (1 hunks)
  • v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1 hunks)
  • v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js (1 hunks)
  • v3/examples/websocket-transport/main.go (1 hunks)
  • v3/examples/websocket-transport/transport_websocket.go (1 hunks)
  • v3/go.mod (1 hunks)
  • v3/internal/assetserver/bundledassets/runtime.js (1 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts (1 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts (1 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (1 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (3 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts (2 hunks)
  • v3/internal/runtime/runtime.go (1 hunks)
  • v3/internal/runtime/runtime_darwin.go (0 hunks)
  • v3/internal/runtime/runtime_linux.go (0 hunks)
  • v3/internal/runtime/runtime_windows.go (0 hunks)
  • v3/pkg/application/CUSTOM_TRANSPORT.md (1 hunks)
  • v3/pkg/application/application.go (2 hunks)
  • v3/pkg/application/application_options.go (1 hunks)
  • v3/pkg/application/event_manager.go (0 hunks)
  • v3/pkg/application/messageprocessor.go (4 hunks)
  • v3/pkg/application/messageprocessor_application.go (2 hunks)
  • v3/pkg/application/messageprocessor_args.go (1 hunks)
  • v3/pkg/application/messageprocessor_browser.go (1 hunks)
  • v3/pkg/application/messageprocessor_call.go (4 hunks)
  • v3/pkg/application/messageprocessor_clipboard.go (2 hunks)
  • v3/pkg/application/messageprocessor_contextmenu.go (2 hunks)
  • v3/pkg/application/messageprocessor_dialog.go (4 hunks)
  • v3/pkg/application/messageprocessor_events.go (2 hunks)
  • v3/pkg/application/messageprocessor_params.go (0 hunks)
  • v3/pkg/application/messageprocessor_screens.go (2 hunks)
  • v3/pkg/application/messageprocessor_system.go (1 hunks)
  • v3/pkg/application/messageprocessor_window.go (4 hunks)
  • v3/pkg/application/transport.go (1 hunks)
  • v3/pkg/application/transport_event_ipc.go (1 hunks)
  • v3/pkg/application/transport_http.go (1 hunks)
  • v3/pkg/application/webview_window.go (0 hunks)
  • v3/pkg/application/webview_window_darwin.go (5 hunks)
  • v3/pkg/application/webview_window_linux.go (1 hunks)
  • v3/pkg/application/webview_window_windows.go (1 hunks)
  • v3/pkg/application/window.go (1 hunks)
  • v3/pkg/errs/README.md (1 hunks)
  • v3/pkg/errs/codegen/error_functions/main.go (1 hunks)
  • v3/pkg/errs/error_functions.gen.go (1 hunks)
  • v3/pkg/errs/errors.go (1 hunks)
  • v3/pkg/errs/utils.go (1 hunks)
  • v3/tests/window-visibility-test/go.mod (1 hunks)
💤 Files with no reviewable changes (6)
  • v3/pkg/application/event_manager.go
  • v3/internal/runtime/runtime_darwin.go
  • v3/pkg/application/webview_window.go
  • v3/internal/runtime/runtime_linux.go
  • v3/internal/runtime/runtime_windows.go
  • v3/pkg/application/messageprocessor_params.go
🧰 Additional context used
🧠 Learnings (15)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
📚 Learning: 2025-01-15T22:33:30.639Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4001
File: v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts:0-0
Timestamp: 2025-01-15T22:33:30.639Z
Learning: In the Wails framework's TypeScript bindings, the import path "/wails/runtime.js" is intentionally absolute and should not be changed to a relative path.

Applied to files:

  • v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js
  • v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts
  • v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js
  • v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js
  • v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts
  • v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts
📚 Learning: 2025-01-15T22:33:47.244Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4001
File: v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts:0-0
Timestamp: 2025-01-15T22:33:47.244Z
Learning: In the Wails framework, files with the header comment "Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL" are automatically generated and should not be modified manually.

Applied to files:

  • v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js
  • v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js
📚 Learning: 2025-01-18T21:19:47.778Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4024
File: v3/pkg/application/services.go:38-51
Timestamp: 2025-01-18T21:19:47.778Z
Learning: In the Wails v3 codebase, panic is used to catch invalid invocations that should never occur in production (programming errors), while error returns are reserved for recoverable error conditions (runtime errors). For example, the `NewService` function in `v3/pkg/application/services.go` uses panic to handle the case where more than one `ServiceOptions` instance is provided, as this is considered an unrecoverable programming error.

Applied to files:

  • v3/pkg/application/messageprocessor_dialog.go
  • v3/pkg/application/messageprocessor_events.go
  • v3/pkg/application/messageprocessor_window.go
  • v3/pkg/application/messageprocessor_screens.go
  • v3/pkg/errs/errors.go
  • v3/pkg/application/messageprocessor_clipboard.go
  • v3/pkg/application/messageprocessor_application.go
  • v3/pkg/errs/error_functions.gen.go
📚 Learning: 2025-02-04T23:59:43.956Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4045
File: v3/internal/generator/render/info.go:28-68
Timestamp: 2025-02-04T23:59:43.956Z
Learning: In the Wails v3 project, internal functions are designed to panic on nil parameters as they represent contract violations, rather than adding defensive nil checks.

Applied to files:

  • v3/pkg/application/messageprocessor_dialog.go
  • v3/pkg/application/messageprocessor_events.go
  • v3/pkg/application/messageprocessor_window.go
  • v3/pkg/application/messageprocessor_screens.go
  • v3/pkg/errs/errors.go
  • v3/pkg/application/messageprocessor_clipboard.go
  • v3/pkg/application/messageprocessor_application.go
  • v3/pkg/errs/error_functions.gen.go
📚 Learning: 2025-02-13T01:05:02.267Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4066
File: v3/pkg/application/messageprocessor_call.go:174-174
Timestamp: 2025-02-13T01:05:02.267Z
Learning: When handling JSON marshaling errors in Wails v3, the error message from json.Marshal provides sufficient debugging context. Logging raw data is unnecessary and could make logs harder to read.

Applied to files:

  • v3/pkg/application/messageprocessor_dialog.go
  • v3/pkg/application/messageprocessor_window.go
  • v3/pkg/application/messageprocessor.go
📚 Learning: 2025-10-17T23:16:11.570Z
Learnt from: Sammy-T
Repo: wailsapp/wails PR: 4570
File: v2/internal/frontend/desktop/linux/window_webkit6.go:97-108
Timestamp: 2025-10-17T23:16:11.570Z
Learning: For webkit_6/GTK4 builds in v2/internal/frontend/desktop/linux/window_webkit6.go, GTK widget creation should not be wrapped in invokeOnMainThread. The activation mechanism (activateWg + onActivate export) already handles thread safety, and additional wrapping would cause issues.

Applied to files:

  • v3/pkg/application/webview_window_linux.go
  • v3/pkg/application/webview_window_windows.go
  • v3/pkg/application/webview_window_darwin.go
📚 Learning: 2025-08-08T09:13:16.916Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).

Applied to files:

  • v3/pkg/application/webview_window_linux.go
  • v3/pkg/application/webview_window_windows.go
  • v3/pkg/application/webview_window_darwin.go
  • v3/internal/assetserver/bundledassets/runtime.js
📚 Learning: 2024-09-20T23:34:29.841Z
Learnt from: nixpare
Repo: wailsapp/wails PR: 3763
File: v3/examples/keybindings/main.go:16-17
Timestamp: 2024-09-20T23:34:29.841Z
Learning: In the codebase, `application.Options.KeyBindings` uses the `application.Window` type, whereas `application.WebviewWindowOptions.KeyBindings` uses `*application.WebviewWindow`. This is intentional and acceptable.

Applied to files:

  • v3/pkg/application/webview_window_linux.go
  • v3/pkg/application/webview_window_windows.go
  • v3/pkg/application/webview_window_darwin.go
📚 Learning: 2025-02-25T17:13:05.652Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4100
File: v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts:222-228
Timestamp: 2025-02-25T17:13:05.652Z
Learning: The user has chosen to maintain the function name `Error` in the dialogs module despite it shadowing the global Error constructor. This is a deliberate choice due to documentation generator compatibility concerns, and the risk is mitigated by using `window.Error` when referencing the global constructor and by the strictly type-checked modular nature of the code.

Applied to files:

  • v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts
📚 Learning: 2025-02-13T01:08:11.993Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4066
File: v3/internal/runtime/desktop/@wailsio/runtime/src/calls.js:69-71
Timestamp: 2025-02-13T01:08:11.993Z
Learning: In JavaScript, Promise.resolve() schedules its then/catch callbacks as microtasks that execute asynchronously, so a try/catch block around Promise.resolve() will properly catch any errors that occur in those callbacks.

Applied to files:

  • v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts
📚 Learning: 2024-09-30T06:13:46.595Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 3763
File: v3/examples/window/main.go:472-475
Timestamp: 2024-09-30T06:13:46.595Z
Learning: In `v3/examples/window/main.go`, `time.Sleep` is used within a goroutine and does not block the UI thread.

Applied to files:

  • v3/examples/websocket-transport/main.go
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.

Applied to files:

  • v3/pkg/application/application.go
  • v3/examples/websocket-transport/GreetService.go
📚 Learning: 2025-01-24T22:41:18.566Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 4031
File: v3/pkg/application/menu.go:199-202
Timestamp: 2025-01-24T22:41:18.566Z
Learning: In the Wails menu system (v3/pkg/application/menu.go), shared state between menus is intentionally designed and desirable. Methods like `Append()` and `Prepend()` should maintain shared references to menu items rather than creating deep copies.

Applied to files:

  • v3/pkg/application/messageprocessor_contextmenu.go
📚 Learning: 2025-04-18T05:57:34.711Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 4128
File: v3/examples/gin-service/services/gin_service.go:67-85
Timestamp: 2025-04-18T05:57:34.711Z
Learning: In Wails services (like GinService), initializing the app field in ServiceStartup rather than in the constructor is an acceptable pattern, as ServiceStartup is guaranteed to be called before any HTTP requests are handled.

Applied to files:

  • v3/examples/websocket-transport/GreetService.go
🧬 Code graph analysis (28)
v3/pkg/application/messageprocessor_dialog.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • NewInvalidDialogCallErrorf (174-181)
  • WrapInvalidDialogCallErrorf (183-194)
v3/pkg/application/dialogs.go (3)
  • MessageDialogOptions (72-79)
  • OpenFileDialogOptions (169-187)
  • SaveFileDialogOptions (362-376)
v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)
v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (4)
  • Add (20-22)
  • Echo (29-31)
  • GetTime (37-39)
  • Greet (46-48)
v3/pkg/application/webview_window_linux.go (1)
v3/internal/runtime/runtime.go (1)
  • Core (10-20)
v3/pkg/application/messageprocessor_system.go (4)
v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts (3)
  • Environment (87-89)
  • Capabilities (54-56)
  • IsDarkMode (45-47)
v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (1)
  • Flags (38-38)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/errs/error_functions.gen.go (1)
  • NewInvalidSystemCallErrorf (114-121)
v3/pkg/application/application_options.go (1)
v3/pkg/application/transport.go (1)
  • Transport (18-26)
v3/pkg/application/transport.go (1)
v3/pkg/application/messageprocessor.go (1)
  • MessageProcessor (65-70)
v3/pkg/application/messageprocessor_events.go (5)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/window.go (1)
  • Window (9-104)
v3/pkg/application/events.go (1)
  • CustomEvent (52-58)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • WrapInvalidEventsCallErrorf (333-344)
  • NewInvalidEventsCallErrorf (324-331)
v3/pkg/application/messageprocessor_call.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (4)
  • NewInvalidBindingCallErrorf (264-271)
  • WrapInvalidBindingCallErrorf (273-284)
  • NewBindingCallFailedErrorf (294-301)
  • WrapBindingCallFailedErrorf (303-314)
v3/pkg/application/bindings.go (6)
  • CallOptions (17-21)
  • BoundMethod (68-79)
  • CallError (31-35)
  • ReferenceError (26-26)
  • TypeError (27-27)
  • RuntimeError (28-28)
v3/pkg/application/webview_window_windows.go (1)
v3/internal/runtime/runtime.go (1)
  • Core (10-20)
v3/pkg/application/messageprocessor_browser.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • NewInvalidBrowserCallErrorf (84-91)
  • WrapInvalidBrowserCallErrorf (93-104)
v3/pkg/application/urlvalidator.go (1)
  • ValidateAndSanitizeURL (11-49)
v3/pkg/application/transport_event_ipc.go (2)
v3/pkg/application/application.go (1)
  • App (306-397)
v3/pkg/application/events.go (1)
  • CustomEvent (52-58)
v3/pkg/application/transport_http.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • WrapInvalidRuntimeCallErrorf (363-374)
  • NewInvalidRuntimeCallErrorf (354-361)
v3/pkg/application/bindings.go (1)
  • CallError (31-35)
v3/pkg/application/messageprocessor_window.go (5)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/window.go (1)
  • Window (9-104)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • NewInvalidWindowCallErrorf (24-31)
  • WrapInvalidWindowCallErrorf (33-44)
v3/pkg/application/webview_window_options.go (1)
  • RGBA (145-147)
v3/pkg/application/messageprocessor_screens.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/screenmanager.go (1)
  • Screen (25-38)
v3/pkg/application/window.go (1)
  • Window (9-104)
v3/pkg/errs/error_functions.gen.go (2)
  • WrapInvalidScreensCallErrorf (153-164)
  • NewInvalidScreensCallErrorf (144-151)
v3/examples/websocket-transport/main.go (4)
v3/examples/websocket-transport/transport_websocket.go (1)
  • NewWebSocketTransport (52-70)
v3/pkg/application/application.go (1)
  • New (48-195)
v3/pkg/application/application_options.go (2)
  • Options (12-117)
  • MacOptions (187-193)
v3/pkg/application/transport.go (1)
  • Transport (18-26)
v3/pkg/application/application.go (5)
v3/pkg/application/transport.go (3)
  • Transport (18-26)
  • TransportHTTPHandler (65-67)
  • AssetServerTransport (40-54)
v3/pkg/application/transport_http.go (2)
  • NewHTTPTransport (20-31)
  • HTTPTransportWithLogger (37-41)
v3/pkg/application/events.go (1)
  • WailsEventListener (83-85)
v3/pkg/application/transport_event_ipc.go (1)
  • EventIPCTransport (3-5)
v3/pkg/application/application_options.go (1)
  • Options (12-117)
v3/pkg/errs/errors.go (1)
v3/pkg/errs/utils.go (1)
  • Cause (21-37)
v3/pkg/application/messageprocessor_contextmenu.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/window.go (1)
  • Window (9-104)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • WrapInvalidContextMenuCallErrorf (213-224)
  • NewInvalidContextMenuCallErrorf (204-211)
v3/pkg/application/messageprocessor_clipboard.go (3)
v3/pkg/application/messageprocessor.go (1)
  • RuntimeRequest (44-63)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • WrapInvalidClipboardCallErrorf (243-254)
  • NewInvalidClipboardCallErrorf (234-241)
v3/examples/websocket-transport/assets/websocket-transport.js (2)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
  • nanoid (16-16)
  • clientId (32-32)
v3/internal/assetserver/bundledassets/runtime.debug.js (7)
  • id (69-69)
  • id (208-208)
  • id (2460-2460)
  • i (70-70)
  • i (1066-1066)
  • i (1414-1414)
  • callId (160-160)
v3/pkg/application/messageprocessor.go (3)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (1)
  • NewInvalidRuntimeCallErrorf (354-361)
v3/pkg/application/window.go (1)
  • Window (9-104)
v3/pkg/application/messageprocessor_application.go (2)
v3/pkg/application/messageprocessor.go (1)
  • RuntimeRequest (44-63)
v3/pkg/errs/error_functions.gen.go (1)
  • NewInvalidApplicationCallErrorf (54-61)
v3/pkg/application/webview_window_darwin.go (1)
v3/internal/runtime/runtime.go (1)
  • Core (10-20)
v3/examples/websocket-transport/transport_websocket.go (2)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/events.go (1)
  • CustomEvent (52-58)
v3/pkg/errs/utils.go (1)
v3/pkg/errs/errors.go (2)
  • ErrorType (5-5)
  • WailsError (7-12)
v3/examples/websocket-transport/GreetService.go (4)
v3/pkg/application/application.go (2)
  • App (306-397)
  • Get (44-46)
v3/pkg/application/services.go (2)
  • ServiceStartup (98-100)
  • ServiceOptions (17-40)
v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (4)
  • Greet (46-48)
  • GetTime (37-39)
  • Echo (29-31)
  • Add (20-22)
v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (4)
  • Greet (46-48)
  • GetTime (37-39)
  • Echo (29-31)
  • Add (20-22)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (4)
  • RuntimeTransport (59-59)
  • setTransport (57-57)
  • getTransport (58-58)
  • clientId (61-61)
v3/internal/assetserver/bundledassets/runtime.debug.js (5)
  • method (1155-1155)
  • url (110-110)
  • body (111-114)
  • headers (118-121)
  • response (125-129)
v3/pkg/errs/error_functions.gen.go (2)
v3/pkg/errs/errors.go (13)
  • ErrorType (5-5)
  • InvalidWindowCallError (15-15)
  • InvalidApplicationCallError (16-16)
  • InvalidBrowserCallError (17-17)
  • InvalidSystemCallError (18-18)
  • InvalidScreensCallError (19-19)
  • InvalidDialogCallError (20-20)
  • InvalidContextMenuCallError (21-21)
  • InvalidClipboardCallError (22-22)
  • InvalidBindingCallError (23-23)
  • BindingCallFailedError (24-24)
  • InvalidEventsCallError (25-25)
  • InvalidRuntimeCallError (26-26)
v3/pkg/errs/utils.go (3)
  • Cause (21-37)
  • Is (9-19)
  • Has (39-57)
🪛 Biome (2.1.2)
v3/internal/assetserver/bundledassets/runtime.js

[error] 1-1: This array contains an empty slots..

The presences of empty slots may cause incorrect information and might be a typo.
Unsafe fix: Replace hole with undefined

(lint/suspicious/noSparseArray)


[error] 1-1: Do not add then to a class.

(lint/suspicious/noThenProperty)


[error] 1-1: Shouldn't redeclare 'i'. Consider to delete it or rename it.

'i' is defined here:

(lint/suspicious/noRedeclare)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)

🪛 markdownlint-cli2 (0.18.1)
v3/examples/websocket-transport/README.md

15-15: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

v3/pkg/application/CUSTOM_TRANSPORT.md

15-15: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
🔇 Additional comments (27)
v3/examples/gin-service/go.mod (1)

60-60: Dependency bump is reasonable.

The go-webview2 v1.0.21 → v1.0.22 bump is a patch version increment that aligns with coordinated updates across the codebase and the PR's transport layer refactoring goals.

v3/examples/file-association/go.mod (1)

39-39: Dependency bump is consistent with coordinated updates.

Part of the systematic go-webview2 v1.0.22 update across example modules.

v3/examples/dev/go.mod (1)

39-39: Dependency bump is consistent with coordinated updates.

Part of the systematic go-webview2 v1.0.22 update across example modules.

v3/go.mod (2)

38-38: Dependency bump is consistent across the codebase.

The go-webview2 v1.0.21 → v1.0.22 bump in the main module aligns with updates across all example and test modules.


20-20: WebSocket dependency addition uses current, secure version.

The gorilla/websocket v1.5.3 dependency is the latest stable release. A CVE-2020-27813 vulnerability in frame length handling was fixed in v1.4.1, so v1.5.3 includes this security patch. No newer security advisories exist for this version. The dependency addition appropriately supports the custom WebSocket transport implementation.

v3/examples/notifications/go.mod (1)

42-42: Dependency bump is consistent with coordinated updates.

Part of the systematic go-webview2 v1.0.22 update across example modules.

v3/examples/gin-example/go.mod (1)

58-58: Dependency bump is consistent with coordinated updates.

Part of the systematic go-webview2 v1.0.22 update across example modules.

v3/tests/window-visibility-test/go.mod (1)

43-43: Dependency bump is consistent with coordinated updates.

Part of the systematic go-webview2 v1.0.22 update across test and example modules.

v3/pkg/application/window.go (1)

5-5: LGTM!

The import formatting change is clean. The removal of the Callback interface (mentioned in the AI summary) aligns with the PR's goal of refactoring to a request/response pattern.

v3/internal/assetserver/bundledassets/runtime.js (1)

1-1: Generated/bundled code - static analysis warnings expected.

This is a minified and bundled JavaScript file. The static analysis warnings (empty slots, redeclare, etc.) are typical for bundled code and can be safely ignored. The source TypeScript files should be reviewed instead if logic verification is needed.

v3/pkg/errs/README.md (1)

1-5: LGTM!

Clear and concise documentation for the errs package. The description of the code generation workflow is helpful for maintainers.

v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts (1)

54-56: Verify the IPC-based capability fetch after fixing the constant collision.

The change from HTTP fetch to IPC call is appropriate for the transport refactoring. However, this will only work correctly after fixing the SystemCapabilities constant value collision flagged in the previous comment.

v3/pkg/application/application_options.go (1)

107-116: LGTM!

The new Transport field is well-documented with clear usage examples. The documentation properly explains the default behavior and when custom transports might be needed.

v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js (1)

1-8: Auto-generated file - no review needed.

This file is automatically generated as indicated by the header comment. The re-export pattern is standard for generated bindings.

v3/pkg/application/webview_window_darwin.go (2)

1358-1403: LGTM!

The whitespace formatting changes in the applyLiquidGlass function improve readability without altering logic.


1094-1094: Code initialization path is sound—no flag initialization risk exists.

The concern about globalApplication.impl.GetFlags(globalApplication.options) executing before proper initialization is unfounded. The execution order is:

  1. NewApplication() populates globalApplication and globalApplication.options
  2. newPlatformApp() is called (Linux variant immediately accesses parent.options.Name during construction, proving options is ready)
  3. Windows are created and hooks are registered
  4. WebViewDidFinishNavigation fires after navigation completes

Additionally, GetFlags() defensively initializes an empty map[string]any if options.Flags is nil, preventing any nil dereference. The same pattern is used consistently across all platforms (Darwin, Linux, Windows).

v3/pkg/application/webview_window_linux.go (1)

355-355: Consistent with Darwin implementation.

The change to pass flags to runtime.Core() matches the pattern used in the Darwin implementation. The same verification concern applies: ensure globalApplication.impl.GetFlags(globalApplication.options) is properly initialized before the WindowLoadChanged event fires.

v3/pkg/application/webview_window_windows.go (1)

2140-2140: LGTM! Core signature correctly updated.

The change properly adapts to the new runtime.Core(flags map[string]any) signature, passing application-specific flags from GetFlags for injection into the webview. This aligns with the PR objective to inject all application-specified flags.

v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (1)

55-62: LGTM! Transport API exports added.

The new export block cleanly exposes the transport-related APIs (setTransport, getTransport, RuntimeTransport, etc.) to support custom transports. The comment clearly documents the purpose of these exports.

v3/examples/websocket-transport/README.md (1)

1-113: LGTM! Clear and comprehensive documentation.

The README provides excellent documentation for the WebSocket transport example, with clear explanations of architecture, setup, and features. The ASCII diagram and code examples enhance understanding.

v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js (1)

1-8: Generated file - no review needed.

This file is automatically generated (as indicated by the header comments). Generated bindings should not be manually modified.

v3/pkg/application/transport_event_ipc.go (1)

7-18: LGTM! Thread-safe event dispatching with proper cancellation handling.

The implementation correctly:

  • Uses RLock for concurrent-safe read access to windows
  • Checks for event cancellation during iteration
  • Properly releases the lock in both early-return and normal-completion paths
  • Dispatches events to all windows efficiently
v3/examples/websocket-transport/main.go (1)

13-58: LGTM! Clear example of custom transport usage.

The example demonstrates the WebSocket transport feature effectively:

  • Simple transport instantiation with NewWebSocketTransport
  • Clear configuration with application options
  • Helpful comments explaining automatic event forwarding
  • Consistent port usage (9099) across the example
v3/examples/websocket-transport/assets/index.html (1)

237-357: LGTM! Comprehensive demo with proper error handling.

The JavaScript implementation demonstrates the WebSocket transport integration well:

  • Proper module imports with cache busting
  • Clean integration with generated bindings
  • Event subscriptions for real-time updates
  • Comprehensive error handling
  • Clear user feedback
v3/pkg/application/messageprocessor_contextmenu.go (1)

31-45: Context menu handler refactor looks solid

The migration to RuntimeRequest plus the standardized invalid-context-menu error propagation is clean and keeps the control flow tight. Nicely done.

v3/pkg/application/messageprocessor_screens.go (1)

19-33: Screen method routing follows the new pattern well

Returning data/errors directly and wrapping failures with errs keeps this aligned with the rest of the processor refactor. Looks good.

v3/examples/gin-routing/go.mod (1)

58-58: Standard patch-level dependency update confirmed safe and compatible.

Verification confirms go-webview2 v1.0.22 is stable (released August 12, 2025) with no security vulnerabilities. The patch version bump (v1.0.21 → v1.0.22) includes a feature addition ("Add source information in message callbacks"), which remains backward compatible and consistent with the PR-wide dependency updates.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 20

🧹 Nitpick comments (7)
v3/pkg/application/transport_event_ipc.go (1)

9-17: Consider deferring the unlock for robustness.

The manual RUnlock paths work today, but a defer immediately after the RLock would make this future-proof against new returns/panics inside the loop.

You could restructure like:

t.app.windowsLock.RLock()
defer t.app.windowsLock.RUnlock()

for _, window := range t.app.windows {
    if event.IsCancelled() {
        return
    }
    window.DispatchWailsEvent(event)
}
v3/internal/runtime/runtime.go (1)

10-19: Core flag injection logic is sound, consider logging marshal errors.

The implementation correctly marshals the flags map to JSON and injects it into the runtime initialization. However, JSON marshal errors are silently ignored (line 14), which could hide issues with invalid flag values at runtime.

Consider adding debug logging for marshal failures to aid troubleshooting:

 func Core(flags map[string]any) string {
 	flagsStr := ""
 	if len(flags) > 0 {
 		f, err := json.Marshal(flags)
-		if err == nil {
+		if err != nil {
+			// Consider: log.Printf("Failed to marshal flags: %v", err) or use slog
+		} else {
 			flagsStr += fmt.Sprintf("window._wails.flags=%s;", f)
 		}
 	}
 
 	return runtimeInit + flagsStr + invoke + environment
 }
v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)

12-12: Consider removing unused import from the generation template.

The $Create import is unused in this generated file. If the code generator template always includes this import, consider updating the template to only import what's needed for each specific binding file.

v3/examples/websocket-transport/assets/websocket-transport.js (1)

31-42: Consider adding a limit to the message queue.

The messageQueue has no size limit. If the WebSocket connection fails for an extended period, the queue could grow unbounded and cause memory issues.

Consider adding a maximum queue size:

 constructor(url, options = {}) {
     this.url = url;
     this.ws = null;
     this.wsReady = false;
     this.pendingRequests = new Map();
     this.messageQueue = [];
     this.reconnectTimer = null;
     this.reconnectDelay = options.reconnectDelay || 2000;
     this.requestTimeout = options.requestTimeout || 30000;
+    this.maxQueueSize = options.maxQueueSize || 100;

     this.connect();
 }

Then enforce the limit when queueing:

 } else {
+    if (this.messageQueue.length >= this.maxQueueSize) {
+        reject(new Error('Message queue full'));
+        return;
+    }
     this.messageQueue.push(message);
     this.connect().catch(reject);
 }
v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)

12-12: Consider removing unused import from the generation template.

Same as the frontend version: the $Create import is unused. This should be addressed in the code generation template to avoid including unused imports.

v3/pkg/application/CUSTOM_TRANSPORT.md (1)

16-31: Add a language identifier to the code fence

Line 16 uses a fenced block without a language tag, which trips markdownlint (MD040). Mark it as text (or another appropriate identifier) so the docs build stays clean.

-```
+```text
 ┌─────────────────────────────────────────────────┐
 │  Frontend (TypeScript)                          │
 │  - Generated bindings still work               │
@@
 └─────────────────────────────────────────────────┘
-```
+```
v3/pkg/errs/error_functions.gen.go (1)

13-13: Consider adding Unwrap() for standard library compatibility.

The wailsError type implements Cause() but not Unwrap() error, which is the standard library interface for error chaining. This means errors.Is() and errors.As() won't automatically walk the error chain, and third-party code expecting Unwrap() won't work. Your custom Is/Has/Cause utilities compensate, but adding Unwrap() as an alias would improve interoperability:

func (w *wailsError) Unwrap() error { return w.cause }

This would make the error chain traversable by both custom and standard library functions.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e4e340 and 3fd6ef2.

⛔ Files ignored due to path filters (8)
  • v3/examples/dev/go.sum is excluded by !**/*.sum
  • v3/examples/file-association/go.sum is excluded by !**/*.sum
  • v3/examples/gin-example/go.sum is excluded by !**/*.sum
  • v3/examples/gin-routing/go.sum is excluded by !**/*.sum
  • v3/examples/gin-service/go.sum is excluded by !**/*.sum
  • v3/examples/notifications/go.sum is excluded by !**/*.sum
  • v3/go.sum is excluded by !**/*.sum
  • v3/tests/window-visibility-test/go.sum is excluded by !**/*.sum
📒 Files selected for processing (58)
  • v3/examples/dev/go.mod (1 hunks)
  • v3/examples/file-association/go.mod (1 hunks)
  • v3/examples/gin-example/go.mod (1 hunks)
  • v3/examples/gin-routing/go.mod (1 hunks)
  • v3/examples/gin-service/go.mod (1 hunks)
  • v3/examples/notifications/go.mod (1 hunks)
  • v3/examples/websocket-transport/GreetService.go (1 hunks)
  • v3/examples/websocket-transport/README.md (1 hunks)
  • v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1 hunks)
  • v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js (1 hunks)
  • v3/examples/websocket-transport/assets/index.html (1 hunks)
  • v3/examples/websocket-transport/assets/websocket-transport.js (1 hunks)
  • v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1 hunks)
  • v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js (1 hunks)
  • v3/examples/websocket-transport/main.go (1 hunks)
  • v3/examples/websocket-transport/transport_websocket.go (1 hunks)
  • v3/go.mod (1 hunks)
  • v3/internal/assetserver/bundledassets/runtime.js (1 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts (1 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts (1 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (1 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (3 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts (2 hunks)
  • v3/internal/runtime/runtime.go (1 hunks)
  • v3/internal/runtime/runtime_darwin.go (0 hunks)
  • v3/internal/runtime/runtime_linux.go (0 hunks)
  • v3/internal/runtime/runtime_windows.go (0 hunks)
  • v3/pkg/application/CUSTOM_TRANSPORT.md (1 hunks)
  • v3/pkg/application/application.go (2 hunks)
  • v3/pkg/application/application_options.go (1 hunks)
  • v3/pkg/application/event_manager.go (0 hunks)
  • v3/pkg/application/messageprocessor.go (4 hunks)
  • v3/pkg/application/messageprocessor_application.go (2 hunks)
  • v3/pkg/application/messageprocessor_args.go (1 hunks)
  • v3/pkg/application/messageprocessor_browser.go (1 hunks)
  • v3/pkg/application/messageprocessor_call.go (4 hunks)
  • v3/pkg/application/messageprocessor_clipboard.go (2 hunks)
  • v3/pkg/application/messageprocessor_contextmenu.go (2 hunks)
  • v3/pkg/application/messageprocessor_dialog.go (4 hunks)
  • v3/pkg/application/messageprocessor_events.go (2 hunks)
  • v3/pkg/application/messageprocessor_params.go (0 hunks)
  • v3/pkg/application/messageprocessor_screens.go (2 hunks)
  • v3/pkg/application/messageprocessor_system.go (1 hunks)
  • v3/pkg/application/messageprocessor_window.go (4 hunks)
  • v3/pkg/application/transport.go (1 hunks)
  • v3/pkg/application/transport_event_ipc.go (1 hunks)
  • v3/pkg/application/transport_http.go (1 hunks)
  • v3/pkg/application/webview_window.go (0 hunks)
  • v3/pkg/application/webview_window_darwin.go (5 hunks)
  • v3/pkg/application/webview_window_linux.go (1 hunks)
  • v3/pkg/application/webview_window_windows.go (1 hunks)
  • v3/pkg/application/window.go (1 hunks)
  • v3/pkg/errs/README.md (1 hunks)
  • v3/pkg/errs/codegen/error_functions/main.go (1 hunks)
  • v3/pkg/errs/error_functions.gen.go (1 hunks)
  • v3/pkg/errs/errors.go (1 hunks)
  • v3/pkg/errs/utils.go (1 hunks)
  • v3/tests/window-visibility-test/go.mod (1 hunks)
💤 Files with no reviewable changes (6)
  • v3/pkg/application/event_manager.go
  • v3/pkg/application/webview_window.go
  • v3/internal/runtime/runtime_darwin.go
  • v3/pkg/application/messageprocessor_params.go
  • v3/internal/runtime/runtime_windows.go
  • v3/internal/runtime/runtime_linux.go
🧰 Additional context used
🧠 Learnings (15)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
📚 Learning: 2025-01-15T22:33:30.639Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4001
File: v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts:0-0
Timestamp: 2025-01-15T22:33:30.639Z
Learning: In the Wails framework's TypeScript bindings, the import path "/wails/runtime.js" is intentionally absolute and should not be changed to a relative path.

Applied to files:

  • v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js
  • v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts
  • v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts
  • v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js
  • v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts
  • v3/internal/assetserver/bundledassets/runtime.js
📚 Learning: 2025-01-15T22:33:47.244Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4001
File: v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts:0-0
Timestamp: 2025-01-15T22:33:47.244Z
Learning: In the Wails framework, files with the header comment "Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL" are automatically generated and should not be modified manually.

Applied to files:

  • v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js
  • v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js
📚 Learning: 2025-01-18T21:19:47.778Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4024
File: v3/pkg/application/services.go:38-51
Timestamp: 2025-01-18T21:19:47.778Z
Learning: In the Wails v3 codebase, panic is used to catch invalid invocations that should never occur in production (programming errors), while error returns are reserved for recoverable error conditions (runtime errors). For example, the `NewService` function in `v3/pkg/application/services.go` uses panic to handle the case where more than one `ServiceOptions` instance is provided, as this is considered an unrecoverable programming error.

Applied to files:

  • v3/pkg/application/messageprocessor_screens.go
  • v3/pkg/application/messageprocessor_application.go
  • v3/pkg/application/messageprocessor_dialog.go
  • v3/pkg/application/messageprocessor_window.go
  • v3/pkg/application/messageprocessor_events.go
  • v3/pkg/errs/codegen/error_functions/main.go
  • v3/pkg/application/messageprocessor_clipboard.go
  • v3/pkg/errs/errors.go
  • v3/pkg/errs/error_functions.gen.go
📚 Learning: 2025-02-04T23:59:43.956Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4045
File: v3/internal/generator/render/info.go:28-68
Timestamp: 2025-02-04T23:59:43.956Z
Learning: In the Wails v3 project, internal functions are designed to panic on nil parameters as they represent contract violations, rather than adding defensive nil checks.

Applied to files:

  • v3/pkg/application/messageprocessor_screens.go
  • v3/pkg/application/messageprocessor_application.go
  • v3/pkg/application/messageprocessor_dialog.go
  • v3/pkg/application/messageprocessor_window.go
  • v3/pkg/application/messageprocessor_events.go
  • v3/pkg/application/messageprocessor_clipboard.go
  • v3/pkg/errs/errors.go
  • v3/pkg/errs/error_functions.gen.go
📚 Learning: 2025-02-13T01:08:11.993Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4066
File: v3/internal/runtime/desktop/@wailsio/runtime/src/calls.js:69-71
Timestamp: 2025-02-13T01:08:11.993Z
Learning: In JavaScript, Promise.resolve() schedules its then/catch callbacks as microtasks that execute asynchronously, so a try/catch block around Promise.resolve() will properly catch any errors that occur in those callbacks.

Applied to files:

  • v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts
📚 Learning: 2025-02-13T01:05:02.267Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4066
File: v3/pkg/application/messageprocessor_call.go:174-174
Timestamp: 2025-02-13T01:05:02.267Z
Learning: When handling JSON marshaling errors in Wails v3, the error message from json.Marshal provides sufficient debugging context. Logging raw data is unnecessary and could make logs harder to read.

Applied to files:

  • v3/pkg/application/messageprocessor_dialog.go
  • v3/pkg/application/messageprocessor_window.go
  • v3/pkg/application/messageprocessor.go
📚 Learning: 2025-08-08T09:13:16.916Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).

Applied to files:

  • v3/pkg/application/messageprocessor_window.go
  • v3/pkg/application/webview_window_linux.go
  • v3/pkg/application/webview_window_darwin.go
  • v3/pkg/application/webview_window_windows.go
  • v3/internal/assetserver/bundledassets/runtime.js
📚 Learning: 2025-01-24T22:41:18.566Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 4031
File: v3/pkg/application/menu.go:199-202
Timestamp: 2025-01-24T22:41:18.566Z
Learning: In the Wails menu system (v3/pkg/application/menu.go), shared state between menus is intentionally designed and desirable. Methods like `Append()` and `Prepend()` should maintain shared references to menu items rather than creating deep copies.

Applied to files:

  • v3/pkg/application/messageprocessor_contextmenu.go
📚 Learning: 2025-02-25T17:13:05.652Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4100
File: v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts:222-228
Timestamp: 2025-02-25T17:13:05.652Z
Learning: The user has chosen to maintain the function name `Error` in the dialogs module despite it shadowing the global Error constructor. This is a deliberate choice due to documentation generator compatibility concerns, and the risk is mitigated by using `window.Error` when referencing the global constructor and by the strictly type-checked modular nature of the code.

Applied to files:

  • v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts
📚 Learning: 2025-04-18T05:57:34.711Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 4128
File: v3/examples/gin-service/services/gin_service.go:67-85
Timestamp: 2025-04-18T05:57:34.711Z
Learning: In Wails services (like GinService), initializing the app field in ServiceStartup rather than in the constructor is an acceptable pattern, as ServiceStartup is guaranteed to be called before any HTTP requests are handled.

Applied to files:

  • v3/examples/websocket-transport/GreetService.go
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.

Applied to files:

  • v3/examples/websocket-transport/GreetService.go
  • v3/examples/websocket-transport/main.go
📚 Learning: 2024-09-30T06:13:46.595Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 3763
File: v3/examples/window/main.go:472-475
Timestamp: 2024-09-30T06:13:46.595Z
Learning: In `v3/examples/window/main.go`, `time.Sleep` is used within a goroutine and does not block the UI thread.

Applied to files:

  • v3/examples/websocket-transport/main.go
📚 Learning: 2025-10-17T23:16:11.570Z
Learnt from: Sammy-T
Repo: wailsapp/wails PR: 4570
File: v2/internal/frontend/desktop/linux/window_webkit6.go:97-108
Timestamp: 2025-10-17T23:16:11.570Z
Learning: For webkit_6/GTK4 builds in v2/internal/frontend/desktop/linux/window_webkit6.go, GTK widget creation should not be wrapped in invokeOnMainThread. The activation mechanism (activateWg + onActivate export) already handles thread safety, and additional wrapping would cause issues.

Applied to files:

  • v3/pkg/application/webview_window_linux.go
  • v3/pkg/application/webview_window_darwin.go
  • v3/pkg/application/webview_window_windows.go
📚 Learning: 2024-09-20T23:34:29.841Z
Learnt from: nixpare
Repo: wailsapp/wails PR: 3763
File: v3/examples/keybindings/main.go:16-17
Timestamp: 2024-09-20T23:34:29.841Z
Learning: In the codebase, `application.Options.KeyBindings` uses the `application.Window` type, whereas `application.WebviewWindowOptions.KeyBindings` uses `*application.WebviewWindow`. This is intentional and acceptable.

Applied to files:

  • v3/pkg/application/webview_window_linux.go
  • v3/pkg/application/webview_window_darwin.go
🧬 Code graph analysis (29)
v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)
v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (4)
  • Add (20-22)
  • Echo (29-31)
  • GetTime (37-39)
  • Greet (46-48)
v3/pkg/application/messageprocessor_screens.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/screenmanager.go (1)
  • Screen (25-38)
v3/pkg/application/window.go (1)
  • Window (9-104)
v3/pkg/errs/error_functions.gen.go (2)
  • WrapInvalidScreensCallErrorf (153-164)
  • NewInvalidScreensCallErrorf (144-151)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (4)
  • RuntimeTransport (59-59)
  • setTransport (57-57)
  • getTransport (58-58)
  • clientId (61-61)
v3/internal/assetserver/bundledassets/runtime.debug.js (5)
  • method (1155-1155)
  • url (110-110)
  • body (111-114)
  • headers (118-121)
  • response (125-129)
v3/pkg/application/messageprocessor_application.go (2)
v3/pkg/application/messageprocessor.go (1)
  • RuntimeRequest (44-63)
v3/pkg/errs/error_functions.gen.go (1)
  • NewInvalidApplicationCallErrorf (54-61)
v3/pkg/application/transport.go (1)
v3/pkg/application/messageprocessor.go (1)
  • MessageProcessor (65-70)
v3/pkg/application/messageprocessor_dialog.go (5)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/window.go (1)
  • Window (9-104)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • NewInvalidDialogCallErrorf (174-181)
  • WrapInvalidDialogCallErrorf (183-194)
v3/pkg/application/dialogs.go (3)
  • MessageDialogOptions (72-79)
  • OpenFileDialogOptions (169-187)
  • SaveFileDialogOptions (362-376)
v3/pkg/application/application_options.go (1)
v3/pkg/application/transport.go (1)
  • Transport (18-26)
v3/pkg/application/messageprocessor_window.go (5)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/window.go (1)
  • Window (9-104)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • NewInvalidWindowCallErrorf (24-31)
  • WrapInvalidWindowCallErrorf (33-44)
v3/pkg/application/webview_window_options.go (1)
  • RGBA (145-147)
v3/pkg/application/messageprocessor_events.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/events.go (1)
  • CustomEvent (52-58)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • WrapInvalidEventsCallErrorf (333-344)
  • NewInvalidEventsCallErrorf (324-331)
v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)
v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (4)
  • Add (20-22)
  • Echo (29-31)
  • GetTime (37-39)
  • Greet (46-48)
v3/examples/websocket-transport/assets/websocket-transport.js (2)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
  • nanoid (16-16)
  • clientId (32-32)
v3/internal/assetserver/bundledassets/runtime.debug.js (7)
  • id (69-69)
  • id (208-208)
  • id (2460-2460)
  • i (70-70)
  • i (1066-1066)
  • i (1414-1414)
  • callId (160-160)
v3/pkg/application/messageprocessor_call.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (4)
  • NewInvalidBindingCallErrorf (264-271)
  • WrapInvalidBindingCallErrorf (273-284)
  • NewBindingCallFailedErrorf (294-301)
  • WrapBindingCallFailedErrorf (303-314)
v3/pkg/application/bindings.go (6)
  • CallOptions (17-21)
  • BoundMethod (68-79)
  • CallError (31-35)
  • ReferenceError (26-26)
  • TypeError (27-27)
  • RuntimeError (28-28)
v3/examples/websocket-transport/transport_websocket.go (2)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/events.go (1)
  • CustomEvent (52-58)
v3/pkg/application/transport_event_ipc.go (2)
v3/pkg/application/application.go (1)
  • App (306-397)
v3/pkg/application/events.go (1)
  • CustomEvent (52-58)
v3/pkg/application/messageprocessor_contextmenu.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/window.go (1)
  • Window (9-104)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • WrapInvalidContextMenuCallErrorf (213-224)
  • NewInvalidContextMenuCallErrorf (204-211)
v3/pkg/application/messageprocessor_clipboard.go (3)
v3/pkg/application/messageprocessor.go (1)
  • RuntimeRequest (44-63)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • WrapInvalidClipboardCallErrorf (243-254)
  • NewInvalidClipboardCallErrorf (234-241)
v3/pkg/application/messageprocessor_browser.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • NewInvalidBrowserCallErrorf (84-91)
  • WrapInvalidBrowserCallErrorf (93-104)
v3/pkg/application/urlvalidator.go (1)
  • ValidateAndSanitizeURL (11-49)
v3/pkg/application/messageprocessor_system.go (4)
v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts (3)
  • Environment (87-89)
  • Capabilities (54-56)
  • IsDarkMode (45-47)
v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (1)
  • Flags (38-38)
v3/pkg/application/messageprocessor.go (1)
  • RuntimeRequest (44-63)
v3/pkg/errs/error_functions.gen.go (1)
  • NewInvalidSystemCallErrorf (114-121)
v3/examples/websocket-transport/GreetService.go (4)
v3/pkg/application/application.go (2)
  • App (306-397)
  • Get (44-46)
v3/pkg/application/services.go (2)
  • ServiceStartup (98-100)
  • ServiceOptions (17-40)
v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (4)
  • Greet (46-48)
  • GetTime (37-39)
  • Echo (29-31)
  • Add (20-22)
v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (4)
  • Greet (46-48)
  • GetTime (37-39)
  • Echo (29-31)
  • Add (20-22)
v3/examples/websocket-transport/main.go (4)
v3/examples/websocket-transport/transport_websocket.go (1)
  • NewWebSocketTransport (52-70)
v3/pkg/application/application.go (1)
  • New (48-195)
v3/pkg/application/application_options.go (2)
  • Options (12-117)
  • BundledAssetFileServer (168-170)
v3/pkg/application/transport.go (1)
  • Transport (18-26)
v3/pkg/application/webview_window_linux.go (1)
v3/internal/runtime/runtime.go (1)
  • Core (10-20)
v3/pkg/errs/utils.go (1)
v3/pkg/errs/errors.go (2)
  • ErrorType (5-5)
  • WailsError (7-12)
v3/pkg/errs/errors.go (1)
v3/pkg/errs/utils.go (1)
  • Cause (21-37)
v3/pkg/application/application.go (10)
v3/pkg/application/transport.go (3)
  • Transport (18-26)
  • TransportHTTPHandler (65-67)
  • AssetServerTransport (40-54)
v3/pkg/application/transport_http.go (2)
  • NewHTTPTransport (20-31)
  • HTTPTransportWithLogger (37-41)
v3/pkg/application/events.go (1)
  • WailsEventListener (83-85)
v3/pkg/application/transport_event_ipc.go (1)
  • EventIPCTransport (3-5)
v3/pkg/application/application_options.go (3)
  • Middleware (144-144)
  • Options (12-117)
  • ChainMiddleware (147-154)
v3/internal/assetserver/middleware.go (2)
  • Middleware (10-10)
  • ChainMiddleware (13-20)
v3/internal/assetserver/common.go (1)
  • ServeFile (29-40)
v3/internal/assetserver/bundledassets/runtime_dev.go (1)
  • RuntimeJS (8-8)
v3/internal/assetserver/bundledassets/runtime_production.go (1)
  • RuntimeJS (8-8)
v3/internal/assetserver/options.go (1)
  • Options (10-29)
v3/pkg/errs/error_functions.gen.go (2)
v3/pkg/errs/errors.go (13)
  • ErrorType (5-5)
  • InvalidWindowCallError (15-15)
  • InvalidApplicationCallError (16-16)
  • InvalidBrowserCallError (17-17)
  • InvalidSystemCallError (18-18)
  • InvalidScreensCallError (19-19)
  • InvalidDialogCallError (20-20)
  • InvalidContextMenuCallError (21-21)
  • InvalidClipboardCallError (22-22)
  • InvalidBindingCallError (23-23)
  • BindingCallFailedError (24-24)
  • InvalidEventsCallError (25-25)
  • InvalidRuntimeCallError (26-26)
v3/pkg/errs/utils.go (3)
  • Cause (21-37)
  • Is (9-19)
  • Has (39-57)
v3/pkg/application/webview_window_darwin.go (1)
v3/internal/runtime/runtime.go (1)
  • Core (10-20)
v3/pkg/application/transport_http.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • WrapInvalidRuntimeCallErrorf (363-374)
  • NewInvalidRuntimeCallErrorf (354-361)
v3/pkg/application/bindings.go (1)
  • CallError (31-35)
v3/pkg/application/webview_window_windows.go (1)
v3/internal/runtime/runtime.go (1)
  • Core (10-20)
v3/pkg/application/messageprocessor.go (2)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (1)
  • NewInvalidRuntimeCallErrorf (354-361)
🪛 Biome (2.1.2)
v3/internal/assetserver/bundledassets/runtime.js

[error] 1-1: This array contains an empty slots..

The presences of empty slots may cause incorrect information and might be a typo.
Unsafe fix: Replace hole with undefined

(lint/suspicious/noSparseArray)


[error] 1-1: Do not add then to a class.

(lint/suspicious/noThenProperty)


[error] 1-1: Shouldn't redeclare 'i'. Consider to delete it or rename it.

'i' is defined here:

(lint/suspicious/noRedeclare)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)

🪛 markdownlint-cli2 (0.18.1)
v3/examples/websocket-transport/README.md

15-15: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

v3/pkg/application/CUSTOM_TRANSPORT.md

16-16: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (32)
v3/examples/gin-example/go.mod (1)

57-57: LGTM: Consistent indirect dependency updates across examples.

The indirect dependency updates (go-webview2 v1.0.21→v1.0.22 and removal of pkg/errors) are consistently applied across all example and test modules. These are automatic results of dependency resolution and align with changes in the main v3 module.

Note: This approval applies to identical changes in v3/examples/dev/go.mod, v3/examples/file-association/go.mod, v3/examples/gin-routing/go.mod, v3/examples/notifications/go.mod, and v3/tests/window-visibility-test/go.mod.

v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (1)

55-62: Confirm public API surface for transport utilities.

The new exports successfully expose the transport abstraction layer, enabling custom transport implementations as outlined in the PR objectives. The RuntimeTransport type and setTransport/getTransport functions provide a clean, typed API for transport customization.

Consider whether objectNames and clientId should be part of the public API. These identifiers appear to be internal runtime details. If they're intended for advanced custom transport implementations, ensure they're documented. If they're purely internal, consider keeping them unexported to reduce public API surface and avoid unintended dependencies.

Can you verify the intended use case for exposing these identifiers?

v3/go.mod (1)

20-20: No changes required—gorilla/websocket v1.5.3 is current and secure.

Verification confirms v1.5.3 is the latest stable release (June 2024). The single security advisory on file only affects versions before 1.4.1; v1.5.3 is unaffected.

v3/examples/gin-service/go.mod (1)

59-59: Dependency bump matches transport updates.

No issues spotted with moving to go-webview2 v1.0.22; the examples stay aligned with the core module.

v3/pkg/application/window.go (1)

9-105: Window surface cleanup looks good.

Removing the legacy Callback embedding matches the new transport design and keeps the public surface tighter.

v3/pkg/errs/README.md (1)

1-5: Helpful README addition.

Clear instructions on extending the errs package—looks good.

v3/pkg/application/webview_window_darwin.go (1)

1094-1094: LGTM!

The updated call to runtime.Core now correctly passes application flags via globalApplication.impl.GetFlags(globalApplication.options), aligning with the new signature and the PR's goal of injecting app-specified flags into the webview at initialization.

v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js (1)

1-8: Auto-generated binding file looks correct.

This is a standard auto-generated binding index that re-exports the GreetService module. No review needed per the file header comment.

v3/pkg/application/application_options.go (1)

107-116: LGTM!

The new Transport field is a well-documented public API addition that enables pluggable IPC transport layers. The comprehensive documentation clearly explains the default behavior and use cases, making this a clean extension point for custom transports like WebSocket.

v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts (1)

54-56: Good: Capabilities now uses IPC instead of HTTP.

The migration from fetch("/wails/capabilities") to IPC-based call(SystemCapabilities) aligns with the PR's goal of decoupling from HTTP transport. Once the duplicate method ID is fixed, this will enable capabilities to work with any transport implementation.

v3/pkg/application/webview_window_linux.go (1)

354-356: LGTM!

The updated runtime.Core call now correctly passes application flags, consistent with the Darwin and Windows implementations. This ensures flags are properly injected across all platforms.

v3/pkg/application/messageprocessor_application.go (1)

19-45: LGTM! Clean refactor to request-driven architecture.

The migration from HTTP-centric to RuntimeRequest-based handling is well executed. The function now returns values instead of side-effecting via HTTP responses, enabling reuse across different transport layers (HTTP, WebSocket, etc.).

v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js (1)

1-8: Auto-generated bindings file.

This file is automatically generated (as indicated by the header comment) and follows the expected pattern for re-exporting service modules in Wails bindings.

v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts (1)

147-153: Excellent simplification of dialog handling.

The removal of custom promise plumbing in favor of directly returning the call() result is cleaner and more maintainable. The finally block ensures proper cleanup regardless of success or failure, which is the idiomatic approach.

v3/pkg/application/webview_window_windows.go (1)

2140-2140: Flag injection properly integrated.

The change enables application-specified flags to be passed to the frontend runtime. This aligns with the PR's goal to inject all app flags (not just resize handle dimensions) into the webview.

v3/examples/websocket-transport/assets/index.html (1)

237-356: Well-structured WebSocket transport example.

The example demonstrates the pluggable transport architecture effectively:

  • Proper initialization with error handling
  • Event subscription using the new transport
  • Generated bindings work seamlessly with custom transport
  • Clear UI feedback for connection status

The hardcoded WebSocket URL (ws://localhost:9099/wails/ws) is appropriate for an example/demo application.

v3/pkg/errs/utils.go (2)

9-19: Clean error type checking implementation.

The Is function properly uses errors.As to check if an error implements WailsError and compares the error type. The nil check prevents panics.


21-37: Correct cause unwrapping logic.

The Cause function follows the standard pattern for unwrapping errors that implement a Cause() method. It properly handles nil causes and missing interfaces.

v3/pkg/application/messageprocessor_contextmenu.go (1)

31-45: Consistent refactor to request-driven architecture.

The changes align with the broader pattern of migrating message processors to use RuntimeRequest and return (any, error). Error handling with the errs package provides consistent error types across the transport layer.

v3/pkg/application/messageprocessor_screens.go (1)

19-34: Well-executed migration to request-driven pattern.

The refactor successfully moves from HTTP-centric to functional return values. Error propagation from Window.GetScreen() is properly wrapped with context, maintaining error chain integrity.

v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)

1-48: LGTM! Auto-generated binding file follows standard pattern.

The generated binding file correctly implements the GreetService methods using the $Call.ByID pattern. All functions properly delegate to the Wails runtime with their respective method IDs.

v3/pkg/application/transport.go (2)

8-26: LGTM! Clean interface design.

The Transport interface is well-designed with clear lifecycle methods and comprehensive documentation explaining its purpose and responsibilities.


28-54: LGTM! Well-designed optional interface.

The AssetServerTransport interface properly embeds Transport and adds asset-serving capability. The documentation clearly explains when and how this interface should be implemented.

v3/pkg/errs/codegen/error_functions/main.go (2)

11-67: LGTM! Template correctly generates error handling functions.

The template generates appropriate constructor, wrapper, and checker functions for each error type with proper error chaining support.


77-86: No type filtering needed—all constants in errors.go are already ErrorType.

Verification confirms that the const block contains only ErrorType constants (12 declarations, each explicitly typed). The current AST inspection correctly collects only ErrorType names without needing defensive type filtering. The suggested diff adds unnecessary complexity and should be disregarded.

Likely an incorrect or invalid review comment.

v3/examples/websocket-transport/assets/websocket-transport.js (3)

108-174: LGTM! Message handling logic is well-implemented.

The handleMessage method properly handles both response and event message types, with appropriate error handling and integration with the Wails runtime.


180-223: LGTM! Runtime call implementation follows the correct pattern.

The call method correctly implements the RuntimeTransport interface with proper timeout handling, request tracking, and message construction.


17-25: Fix array index out of bounds in nanoid implementation.

The alphabet has 60 characters, but Math.random() * 64 can generate indices 0-63, causing array access beyond bounds when the index is 60-63. This results in undefined being added to the ID string.

Apply this diff:

 function nanoid(size = 21) {
     const alphabet = 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict';
     let id = '';
     let i = size;
     while (i--) {
-        id += alphabet[(Math.random() * 64) | 0];
+        id += alphabet[(Math.random() * alphabet.length) | 0];
     }
     return id;
 }

Likely an incorrect or invalid review comment.

v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)

1-48: LGTM! Duplicate auto-generated binding for assets directory.

This file is identical to the frontend binding version and serves the asset-serving context. The duplication is expected for auto-generated bindings.

v3/internal/assetserver/bundledassets/runtime.js (1)

1-1: Static analysis warnings are false positives for minified code.

The Biome linter flags sparse arrays, variable redeclarations, and use-before-declaration issues, but these are inherent to minified/bundled JavaScript and do not indicate actual problems. The then property on the CancellablePromise class is correct (it implements the Promise interface). Since this is a generated bundle, manual line-by-line review is impractical; focus should be on integration testing of the runtime API.

v3/pkg/errs/error_functions.gen.go (2)

7-22: LGTM! Error wrapper implementation is correct.

The wailsError struct correctly implements the custom error interface with Cause(), Error(), Msg(), and ErrorType() methods. Error formatting is clear and includes the error chain when a cause is present.


24-382: LGTM! Error constructor patterns are consistent across all types.

All 12 error types follow the same pattern:

  • New*Errorf creates errors without a cause
  • Wrap*Errorf wraps existing errors with nil-safety
  • Is*Error checks immediate error type
  • Has*Error checks the error chain

The implementation is correct and the consistency aids maintainability.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

♻️ Duplicate comments (5)
v3/pkg/application/CUSTOM_TRANSPORT.md (1)

16-31: Language hint added - previous issue resolved.

The architecture diagram now correctly uses the text language identifier, addressing the markdownlint MD040 warning from the previous review.

v3/pkg/application/messageprocessor_clipboard.go (1)

24-27: Validation error correctly surfaced - previous issue resolved.

The code now correctly uses errs.NewInvalidClipboardCallErrorf instead of wrapping a nil error, ensuring the validation failure is properly returned to the caller.

v3/pkg/application/transport_http.go (3)

73-130: Error handling improved - previous issue resolved.

All error paths in handleRuntimeRequest now correctly return after calling httpError, preventing fall-through and potential nil dereferences.


142-160: Set headers before calling WriteHeader.

Lines 143-144 call WriteHeader before setting the Content-Type header. This causes the same issue as in text(): the header is set after the response status is written, making it ineffective.

Apply this diff:

 func (t *HTTPTransport) json(rw http.ResponseWriter, data any) {
-	rw.WriteHeader(http.StatusOK)
 	rw.Header().Set("Content-Type", "application/json")
+	rw.WriteHeader(http.StatusOK)
 	// convert data to json
 	var jsonPayload = []byte("{}")
 	var err error
 	if data != nil {
 		jsonPayload, err = json.Marshal(data)
 		if err != nil {
 			t.error("Unable to convert data to JSON. Please report this to the Wails team!", "error", err)
 			return
 		}
 	}
 	_, err = rw.Write(jsonPayload)
 	if err != nil {
 		t.error("Unable to write json payload. Please report this to the Wails team!", "error", err)
 		return
 	}
 }

132-140: Set headers before calling WriteHeader.

Lines 133-134 call WriteHeader before setting the Content-Type header. Once WriteHeader is called, the header map is frozen and subsequent Header().Set() calls have no effect. The client won't receive the Content-Type header.

Apply this diff:

 func (t *HTTPTransport) text(rw http.ResponseWriter, data string) {
-	rw.WriteHeader(http.StatusOK)
 	rw.Header().Set("Content-Type", "text/plain")
+	rw.WriteHeader(http.StatusOK)
 	_, err := rw.Write([]byte(data))
 	if err != nil {
 		t.error("Unable to write json payload. Please report this to the Wails team!", "error", err)
 		return
 	}
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3fd6ef2 and 2ecde91.

⛔ Files ignored due to path filters (1)
  • v3/tests/window-visibility-test/go.sum is excluded by !**/*.sum
📒 Files selected for processing (11)
  • v3/examples/websocket-transport/transport_websocket.go (1 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts (2 hunks)
  • v3/pkg/application/CUSTOM_TRANSPORT.md (1 hunks)
  • v3/pkg/application/application.go (2 hunks)
  • v3/pkg/application/messageprocessor_args.go (1 hunks)
  • v3/pkg/application/messageprocessor_clipboard.go (2 hunks)
  • v3/pkg/application/messageprocessor_dialog.go (4 hunks)
  • v3/pkg/application/transport_http.go (1 hunks)
  • v3/pkg/errs/codegen/error_functions/main.go (1 hunks)
  • v3/pkg/errs/errors.go (1 hunks)
  • v3/pkg/errs/utils.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts
  • v3/pkg/errs/utils.go
  • v3/pkg/application/messageprocessor_args.go
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
📚 Learning: 2025-01-18T21:19:47.778Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4024
File: v3/pkg/application/services.go:38-51
Timestamp: 2025-01-18T21:19:47.778Z
Learning: In the Wails v3 codebase, panic is used to catch invalid invocations that should never occur in production (programming errors), while error returns are reserved for recoverable error conditions (runtime errors). For example, the `NewService` function in `v3/pkg/application/services.go` uses panic to handle the case where more than one `ServiceOptions` instance is provided, as this is considered an unrecoverable programming error.

Applied to files:

  • v3/pkg/errs/errors.go
  • v3/pkg/application/messageprocessor_dialog.go
  • v3/pkg/errs/codegen/error_functions/main.go
  • v3/pkg/application/messageprocessor_clipboard.go
📚 Learning: 2025-02-04T23:59:43.956Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4045
File: v3/internal/generator/render/info.go:28-68
Timestamp: 2025-02-04T23:59:43.956Z
Learning: In the Wails v3 project, internal functions are designed to panic on nil parameters as they represent contract violations, rather than adding defensive nil checks.

Applied to files:

  • v3/pkg/errs/errors.go
  • v3/pkg/application/messageprocessor_dialog.go
  • v3/pkg/application/messageprocessor_clipboard.go
📚 Learning: 2024-09-30T06:13:46.595Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 3763
File: v3/examples/window/main.go:472-475
Timestamp: 2024-09-30T06:13:46.595Z
Learning: In `v3/examples/window/main.go`, `time.Sleep` is used within a goroutine and does not block the UI thread.

Applied to files:

  • v3/pkg/application/messageprocessor_dialog.go
📚 Learning: 2024-10-08T22:11:37.054Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 3763
File: v3/internal/commands/appimage_testfiles/main.go:295-299
Timestamp: 2024-10-08T22:11:37.054Z
Learning: In `v3/internal/commands/appimage_testfiles/main.go`, `time.Sleep` is used within a goroutine and does not block the UI thread.

Applied to files:

  • v3/pkg/application/messageprocessor_dialog.go
📚 Learning: 2025-02-13T01:05:02.267Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4066
File: v3/pkg/application/messageprocessor_call.go:174-174
Timestamp: 2025-02-13T01:05:02.267Z
Learning: When handling JSON marshaling errors in Wails v3, the error message from json.Marshal provides sufficient debugging context. Logging raw data is unnecessary and could make logs harder to read.

Applied to files:

  • v3/pkg/application/messageprocessor_dialog.go
📚 Learning: 2025-04-18T05:57:34.711Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 4128
File: v3/examples/gin-service/services/gin_service.go:67-85
Timestamp: 2025-04-18T05:57:34.711Z
Learning: In Wails services (like GinService), initializing the app field in ServiceStartup rather than in the constructor is an acceptable pattern, as ServiceStartup is guaranteed to be called before any HTTP requests are handled.

Applied to files:

  • v3/pkg/application/application.go
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.

Applied to files:

  • v3/pkg/application/application.go
🧬 Code graph analysis (6)
v3/pkg/errs/errors.go (1)
v3/pkg/errs/utils.go (1)
  • Cause (20-40)
v3/pkg/application/messageprocessor_dialog.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • NewInvalidDialogCallErrorf (174-181)
  • WrapInvalidDialogCallErrorf (183-194)
v3/pkg/application/dialogs.go (3)
  • MessageDialogOptions (72-79)
  • OpenFileDialogOptions (169-187)
  • SaveFileDialogOptions (362-376)
v3/pkg/application/application.go (5)
v3/pkg/application/transport.go (3)
  • Transport (18-26)
  • TransportHTTPHandler (65-67)
  • AssetServerTransport (40-54)
v3/pkg/application/transport_http.go (2)
  • NewHTTPTransport (20-31)
  • HTTPTransportWithLogger (37-41)
v3/pkg/application/events.go (1)
  • WailsEventListener (83-85)
v3/pkg/application/transport_event_ipc.go (1)
  • EventIPCTransport (3-5)
v3/internal/assetserver/common.go (1)
  • ServeFile (29-40)
v3/pkg/application/messageprocessor_clipboard.go (3)
v3/pkg/application/messageprocessor.go (1)
  • RuntimeRequest (44-63)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (1)
  • NewInvalidClipboardCallErrorf (234-241)
v3/pkg/application/transport_http.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • WrapInvalidRuntimeCallErrorf (363-374)
  • NewInvalidRuntimeCallErrorf (354-361)
v3/pkg/application/bindings.go (1)
  • CallError (31-35)
v3/examples/websocket-transport/transport_websocket.go (3)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/examples/websocket-transport/assets/websocket-transport.js (1)
  • WebSocketTransport (30-248)
v3/pkg/application/events.go (1)
  • CustomEvent (52-58)
🪛 LanguageTool
v3/pkg/application/CUSTOM_TRANSPORT.md

[grammar] ~37-~37: Uncountable nouns are usually not used with an indefinite article. Use simply “custom transport”.
Context: ...plement the Transport Interface Create a custom transport by implementing the Transport interfa...

(A_UNCOUNTABLE)


[formatting] ~84-~84: These punctuation marks differ from each other. Use only one if you are ending a sentence.
Context: ...ace that will be used to handle requests.: ```typescript const { setTransport } =...

(DOUBLE_PUNCTUATION_PREMIUM)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
  • GitHub Check: semgrep-cloud-platform/scan

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
v3/pkg/application/transport.go (1)

59-62: Clarify TransportHTTPHandler middleware description

The new sentence is hard to parse (“use Handler() in asset server middlewares…”). Please rewrite it as clear, complete sentences so it’s obvious that Wails calls Handler() after Start() to wrap the asset server handler for wails:// requests.

-// When a transport implements this interface, Wails will use Handler() in
-// asset server middlewares that may provide handling for request done from webview to wails:// URLs.
+// When a transport implements this interface, Wails will call Handler() after Start()
+// to obtain middleware that wraps the asset server handler. Use it to intercept
+// requests coming from the webview (wails:// URLs) before they reach the asset server.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2ecde91 and a2b32e8.

📒 Files selected for processing (8)
  • v3/examples/websocket-transport/GreetService.go (1 hunks)
  • v3/examples/websocket-transport/README.md (1 hunks)
  • v3/examples/websocket-transport/assets/websocket-transport.js (1 hunks)
  • v3/examples/websocket-transport/main.go (1 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts (1 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (3 hunks)
  • v3/pkg/application/messageprocessor_call.go (4 hunks)
  • v3/pkg/application/transport.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • v3/examples/websocket-transport/main.go
  • v3/examples/websocket-transport/GreetService.go
  • v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
📚 Learning: 2025-01-15T22:33:30.639Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4001
File: v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts:0-0
Timestamp: 2025-01-15T22:33:30.639Z
Learning: In the Wails framework's TypeScript bindings, the import path "/wails/runtime.js" is intentionally absolute and should not be changed to a relative path.

Applied to files:

  • v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts
🧬 Code graph analysis (4)
v3/pkg/application/messageprocessor_call.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (4)
  • NewInvalidBindingCallErrorf (264-271)
  • WrapInvalidBindingCallErrorf (273-284)
  • NewBindingCallFailedErrorf (294-301)
  • WrapBindingCallFailedErrorf (303-314)
v3/pkg/application/bindings.go (3)
  • CallOptions (17-21)
  • BoundMethod (68-79)
  • CallError (31-35)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (4)
  • RuntimeTransport (59-59)
  • setTransport (57-57)
  • getTransport (58-58)
  • clientId (61-61)
v3/internal/assetserver/bundledassets/runtime.debug.js (5)
  • method (1155-1155)
  • url (110-110)
  • body (111-114)
  • headers (118-121)
  • response (125-129)
v3/pkg/application/transport.go (1)
v3/pkg/application/messageprocessor.go (1)
  • MessageProcessor (65-70)
v3/examples/websocket-transport/assets/websocket-transport.js (2)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
  • nanoid (16-16)
  • clientId (32-32)
v3/internal/assetserver/bundledassets/runtime.debug.js (7)
  • id (69-69)
  • id (208-208)
  • id (2460-2460)
  • i (70-70)
  • i (1066-1066)
  • i (1414-1414)
  • callId (160-160)
🪛 LanguageTool
v3/examples/websocket-transport/README.md

[grammar] ~3-~3: Uncountable nouns are usually not used with an indefinite article. Use simply “custom transport”.
Context: ...e This example demonstrates how to use a custom transport like WebSocket for Wails IPC instead of...

(A_UNCOUNTABLE)


[uncategorized] ~46-~46: The preposition ‘for’ seems more likely in this position.
Context: ... the UI - WebSocket server listening on ws://localhost:9099/wails/ws - Rea...

(AI_HYDRA_LEO_REPLACE_ON_FOR)

🔇 Additional comments (2)
v3/pkg/application/messageprocessor_call.go (1)

118-130: Good catch on propagating non-CallError failures

Thanks for wrapping unexpected errors coming back from boundMethod.Call; this keeps runtime callers from getting silent null results when something actually failed.

v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (1)

101-129: Thanks for preserving falsy args

Great change on the default transport: keeping args when they’re 0, false, or "" avoids the regression we worried about earlier, and the custom transport hook mirrors the new POST workflow nicely.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (4)
v3/examples/websocket-transport/transport_websocket.go (2)

118-133: Stop() must not clear the clients map before deferred cleanups complete.

When Stop() replaces w.clients with a new map (line 129), any deferred cleanup in handleWebSocket (lines 150-156) that subsequently tries to close(w.clients[conn]) will find nil and panic with "close of nil channel."

The past review comment on lines 150-156 suggested capturing messageChan at the top of handleWebSocket and closing the captured variable in the defer, but that change was not applied here.

Apply this fix in Stop():

 func (w *WebSocketTransport) Stop() error {
 	if w.server == nil {
 		return nil
 	}
 
-	// Close all client connections
 	w.mu.Lock()
 	for conn := range w.clients {
 		conn.Close()
 	}
-	w.clients = make(map[*websocket.Conn]chan *WebSocketMessage)
 	w.mu.Unlock()
 
 	return w.server.Shutdown(context.Background())
 }

And update the defer in handleWebSocket (see next comment).


150-157: Capture and close the local messageChan, not the map lookup.

Line 153 closes w.clients[conn], which evaluates to nil if Stop() has already removed the entry from the map, causing a panic. The past review explicitly recommended capturing messageChan in a local variable immediately after line 144 and closing that captured value in the defer.

Apply this diff:

 	w.mu.Lock()
 	messageChan := make(chan *WebSocketMessage, 100)
 	w.clients[conn] = messageChan
 	w.mu.Unlock()
 
 	ctx, cancel := context.WithCancel(r.Context())
 
 	defer func() {
 		w.mu.Lock()
-		cancel()
-		close(w.clients[conn])
-		delete(w.clients, conn)
+		if _, ok := w.clients[conn]; ok {
+			delete(w.clients, conn)
+		}
 		w.mu.Unlock()
+		cancel()
+		close(messageChan)
 		conn.Close()
 	}()
v3/pkg/application/transport_http.go (2)

142-160: Headers must be set before WriteHeader is called.

Lines 143-144 call WriteHeader before Header().Set, which means the Content-Type header will not be sent. Headers must be set before WriteHeader is called.

Apply this diff to fix the header ordering:

 func (t *HTTPTransport) json(rw http.ResponseWriter, data any) {
-	rw.WriteHeader(http.StatusOK)
 	rw.Header().Set("Content-Type", "application/json")
+	rw.WriteHeader(http.StatusOK)
 	// convert data to json
 	var jsonPayload = []byte("{}")
 	var err error
 	if data != nil {
 		jsonPayload, err = json.Marshal(data)
 		if err != nil {
 			t.error("Unable to convert data to JSON. Please report this to the Wails team!", "error", err)
 			return
 		}
 	}
 	_, err = rw.Write(jsonPayload)
 	if err != nil {
 		t.error("Unable to write json payload. Please report this to the Wails team!", "error", err)
 		return
 	}
 }

132-140: Headers must be set before WriteHeader is called.

Lines 133-134 call WriteHeader before Header().Set, which means the Content-Type header will not be sent. In Go's net/http, once WriteHeader or Write is called, headers are flushed and further Header().Set calls are ignored.

Apply this diff to fix the header ordering:

 func (t *HTTPTransport) text(rw http.ResponseWriter, data string) {
-	rw.WriteHeader(http.StatusOK)
 	rw.Header().Set("Content-Type", "text/plain")
+	rw.WriteHeader(http.StatusOK)
 	_, err := rw.Write([]byte(data))
 	if err != nil {
-		t.error("Unable to write json payload. Please report this to the Wails team!", "error", err)
+		t.error("Unable to write text payload. Please report this to the Wails team!", "error", err)
 		return
 	}
 }

Note: Also fixed the error message on line 137 which incorrectly referenced "json payload" instead of "text payload".

🧹 Nitpick comments (3)
v3/pkg/application/CUSTOM_TRANSPORT.md (1)

35-37: Minor grammar refinement.

Per static analysis, "custom transport" (uncountable) reads more idiomatically than "a custom transport" in this technical context.

-Create a custom transport by implementing the `Transport` interface:
+Create custom transport by implementing the `Transport` interface:
v3/examples/websocket-transport/transport_websocket.go (1)

237-251: Consider non-blocking sends for event broadcasting in production.

The current implementation holds RLock during the broadcast loop (lines 245-250). If any client's channel is full, the send on line 249 blocks, stalling all concurrent operations that need the lock. For production use, consider a non-blocking send with a select-default or a timeout to drop events for slow clients rather than blocking all others.

Example pattern for non-blocking send:

for _, channel := range w.clients {
    select {
    case channel <- msg:
        // Sent successfully
    default:
        // Channel full, drop event or log
        log.Printf("[WebSocket] Dropped event for slow client")
    }
}
v3/pkg/application/transport_http.go (1)

73-130: LGTM with minor suggestions.

The request handling logic is correct, with proper error handling and early returns. The validation and processing flow is clean.

Two minor consistency suggestions:

  1. Line 108: Consider defining a constant for "x-wails-client-id" to match the pattern used for webViewRequestHeaderWindowId and webViewRequestHeaderWindowName (lines 97, 107).

  2. Lines 98-114: The windowId undergoes string → int → uint32 conversion. While strconv.Atoi returns an error for invalid input, a negative integer would become a large uint32 after the cast on line 114, which may not be the intended behavior. If window IDs are always non-negative, consider using strconv.ParseUint directly to match the target type.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a2b32e8 and db4c7ac.

📒 Files selected for processing (3)
  • v3/examples/websocket-transport/transport_websocket.go (1 hunks)
  • v3/pkg/application/CUSTOM_TRANSPORT.md (1 hunks)
  • v3/pkg/application/transport_http.go (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
📚 Learning: 2025-08-08T09:13:16.916Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).

Applied to files:

  • v3/pkg/application/transport_http.go
📚 Learning: 2025-08-08T13:15:20.339Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4484
File: v2/internal/frontend/utils/urlValidator.go:25-31
Timestamp: 2025-08-08T13:15:20.339Z
Learning: In Wails v2 (PR wailsapp/wails#4484), for BrowserOpenURL URL validation (v2/internal/frontend/utils/urlValidator.go), maintainers (APshenkin) prefer not to restrict schemes to an http/https allowlist because supported schemes may vary. The allowlist suggestion is declined; continue with the existing denylist approach and generic validation.

Applied to files:

  • v3/pkg/application/transport_http.go
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.

Applied to files:

  • v3/examples/websocket-transport/transport_websocket.go
🧬 Code graph analysis (2)
v3/pkg/application/transport_http.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • WrapInvalidRuntimeCallErrorf (363-374)
  • NewInvalidRuntimeCallErrorf (354-361)
v3/pkg/application/bindings.go (1)
  • CallError (31-35)
v3/examples/websocket-transport/transport_websocket.go (3)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/events.go (1)
  • CustomEvent (52-58)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
🪛 LanguageTool
v3/pkg/application/CUSTOM_TRANSPORT.md

[grammar] ~37-~37: Uncountable nouns are usually not used with an indefinite article. Use simply “custom transport”.
Context: ...plement the Transport Interface Create a custom transport by implementing the Transport interfa...

(A_UNCOUNTABLE)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
🔇 Additional comments (10)
v3/examples/websocket-transport/transport_websocket.go (5)

56-59: CheckOrigin security posture is acceptable for an example.

The blanket return true allows any origin to connect. The inline comment correctly warns that production code must validate origins. Given the disclaimer on lines 17-18 that this is an example and not production-ready, this is appropriate.


159-179: Writer goroutine correctly exits on channel close.

The !ok check on line 164 ensures the goroutine returns immediately when messageChan is closed, avoiding the busy-loop that would otherwise consume CPU. The lock is only acquired when a message is available.


181-196: Reader loop correctly handles connection lifecycle.

The loop properly detects unexpected close errors (line 186) and spawns concurrent request handlers (line 194) with the per-connection context, allowing multiple in-flight calls without blocking the reader.


199-207: Context is correctly propagated to the runtime handler.

Line 204 passes the per-connection ctx to HandleRuntimeCallWithIDs, ensuring that long-running binding calls are cancelled when the WebSocket disconnects or the app shuts down.


209-235: Response handling correctly defaults to success and guards against context cancellation.

The response defaults to StatusCode: 200 (line 212), so successful calls that return nil error are now reported as success. The ctx.Done() check (line 230) prevents sends after the connection context is cancelled, which aligns with the defer in handleWebSocket that cancels ctx before closing messageChan.

v3/pkg/application/transport_http.go (5)

1-18: LGTM!

The package declaration, imports, and struct definition are well-organized and appropriate for an HTTP transport implementation.


20-41: LGTM!

The constructor and functional options pattern are implemented correctly. The logger defaults to slog.Default() and can be customized via the functional option.


43-51: LGTM!

The Start and Stop methods correctly implement the Transport interface. The minimal implementation is appropriate since HTTP transport has no long-lived resources to manage.


53-71: LGTM!

The request struct uses pointers to distinguish between missing and zero values, and the Handler middleware correctly routes /wails/runtime requests while passing others through.


183-185: LGTM!

The error logging helper correctly delegates to the configured logger.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (2)
v3/pkg/application/transport_http.go (2)

142-160: Headers must be set before calling WriteHeader.

Line 143 calls WriteHeader before line 144 sets the Content-Type header. This results in the Content-Type not being set in the response.

Apply this diff to fix the header ordering:

 func (t *HTTPTransport) json(rw http.ResponseWriter, data any) {
-	rw.WriteHeader(http.StatusOK)
 	rw.Header().Set("Content-Type", "application/json")
+	rw.WriteHeader(http.StatusOK)
 	// convert data to json
 	var jsonPayload = []byte("{}")
 	var err error
 	if data != nil {
 		jsonPayload, err = json.Marshal(data)
 		if err != nil {
 			t.error("Unable to convert data to JSON. Please report this to the Wails team!", "error", err)
 			return
 		}
 	}
 	_, err = rw.Write(jsonPayload)
 	if err != nil {
 		t.error("Unable to write json payload. Please report this to the Wails team!", "error", err)
 		return
 	}
 }

132-140: Headers must be set before calling WriteHeader.

Line 133 calls WriteHeader before line 134 sets the Content-Type header. Once WriteHeader is called in Go, the response headers are sent and can no longer be modified, so the Content-Type will not be set.

Apply this diff to fix the header ordering:

 func (t *HTTPTransport) text(rw http.ResponseWriter, data string) {
-	rw.WriteHeader(http.StatusOK)
 	rw.Header().Set("Content-Type", "text/plain")
+	rw.WriteHeader(http.StatusOK)
 	_, err := rw.Write([]byte(data))
 	if err != nil {
 		t.error("Unable to write json payload. Please report this to the Wails team!", "error", err)
 		return
 	}
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between db4c7ac and 5b44587.

📒 Files selected for processing (5)
  • v3/examples/websocket-transport/README.md (1 hunks)
  • v3/examples/websocket-transport/assets/websocket-transport.js (1 hunks)
  • v3/examples/websocket-transport/transport_websocket.go (1 hunks)
  • v3/pkg/application/CUSTOM_TRANSPORT.md (1 hunks)
  • v3/pkg/application/transport_http.go (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.

Applied to files:

  • v3/examples/websocket-transport/transport_websocket.go
📚 Learning: 2025-08-08T09:13:16.916Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).

Applied to files:

  • v3/pkg/application/transport_http.go
  • v3/examples/websocket-transport/assets/websocket-transport.js
  • v3/examples/websocket-transport/README.md
📚 Learning: 2025-08-08T13:15:20.339Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4484
File: v2/internal/frontend/utils/urlValidator.go:25-31
Timestamp: 2025-08-08T13:15:20.339Z
Learning: In Wails v2 (PR wailsapp/wails#4484), for BrowserOpenURL URL validation (v2/internal/frontend/utils/urlValidator.go), maintainers (APshenkin) prefer not to restrict schemes to an http/https allowlist because supported schemes may vary. The allowlist suggestion is declined; continue with the existing denylist approach and generic validation.

Applied to files:

  • v3/pkg/application/transport_http.go
🧬 Code graph analysis (3)
v3/examples/websocket-transport/transport_websocket.go (3)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/examples/websocket-transport/assets/websocket-transport.js (1)
  • WebSocketTransport (30-230)
v3/pkg/application/events.go (1)
  • CustomEvent (52-58)
v3/pkg/application/transport_http.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • WrapInvalidRuntimeCallErrorf (363-374)
  • NewInvalidRuntimeCallErrorf (354-361)
v3/pkg/application/bindings.go (1)
  • CallError (31-35)
v3/examples/websocket-transport/assets/websocket-transport.js (1)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
  • nanoid (16-16)
  • clientId (32-32)
🪛 LanguageTool
v3/pkg/application/CUSTOM_TRANSPORT.md

[grammar] ~37-~37: Uncountable nouns are usually not used with an indefinite article. Use simply “custom transport”.
Context: ...plement the Transport Interface Create a custom transport by implementing the Transport interfa...

(A_UNCOUNTABLE)

v3/examples/websocket-transport/README.md

[grammar] ~3-~3: Uncountable nouns are usually not used with an indefinite article. Use simply “custom transport”.
Context: ...e This example demonstrates how to use a custom transport like WebSocket for Wails IPC instead of...

(A_UNCOUNTABLE)


[uncategorized] ~46-~46: The preposition ‘for’ seems more likely in this position.
Context: ... the UI - WebSocket server listening on ws://localhost:9099/wails/ws - Rea...

(AI_HYDRA_LEO_REPLACE_ON_FOR)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
🔇 Additional comments (5)
v3/pkg/application/transport_http.go (5)

1-42: Well-structured transport setup with functional options.

The package declaration, imports, struct definition, constructor, and functional options follow Go best practices. Previous comment issues have been properly addressed.


43-71: Transport lifecycle and routing logic is correct.

The Start/Stop methods are appropriate, the internal request struct design correctly uses pointers to distinguish missing fields from zero values, and the Handler middleware properly routes the runtime endpoint.


73-130: Request handling logic is robust and correct.

The handler properly validates input, parses headers, delegates to the message processor, and handles errors appropriately. All error paths correctly return immediately, addressing previous review concerns.


162-184: Error response handling is correctly implemented.

This method properly sets Content-Type headers before calling WriteHeader, demonstrating the correct pattern. It appropriately handles both CallError (JSON) and generic errors (plain text).


186-188: Simple and correct error logging helper.

The error method appropriately delegates to the logger with variadic arguments.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
v3/pkg/application/transport_http.go (1)

146-154: Consider returning JSON null for nil payloads.

When data is nil we currently ship "{}", so a Go binding that returns nil (or no values) arrives in the frontend as an empty object. The WebSocket transport emits null, and consumers often distinguish “no result” from “empty object”. Emitting null here keeps the transports consistent and avoids surprising callers.

-	var jsonPayload = []byte("{}")
+	var jsonPayload = []byte("null")
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5b44587 and 68965fd.

📒 Files selected for processing (9)
  • v3/examples/websocket-transport/assets/websocket-transport.js (1 hunks)
  • v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1 hunks)
  • v3/examples/websocket-transport/transport_websocket.go (1 hunks)
  • v3/internal/assetserver/bundledassets/runtime.js (1 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts (1 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts (1 hunks)
  • v3/pkg/application/messageprocessor_dialog.go (4 hunks)
  • v3/pkg/application/transport_event_ipc.go (1 hunks)
  • v3/pkg/application/transport_http.go (1 hunks)
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
📚 Learning: 2025-02-25T17:13:05.652Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4100
File: v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts:222-228
Timestamp: 2025-02-25T17:13:05.652Z
Learning: The user has chosen to maintain the function name `Error` in the dialogs module despite it shadowing the global Error constructor. This is a deliberate choice due to documentation generator compatibility concerns, and the risk is mitigated by using `window.Error` when referencing the global constructor and by the strictly type-checked modular nature of the code.

Applied to files:

  • v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts
📚 Learning: 2025-08-08T09:13:16.916Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).

Applied to files:

  • v3/examples/websocket-transport/assets/websocket-transport.js
  • v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts
  • v3/pkg/application/transport_http.go
📚 Learning: 2025-02-13T01:08:11.993Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4066
File: v3/internal/runtime/desktop/@wailsio/runtime/src/calls.js:69-71
Timestamp: 2025-02-13T01:08:11.993Z
Learning: In JavaScript, Promise.resolve() schedules its then/catch callbacks as microtasks that execute asynchronously, so a try/catch block around Promise.resolve() will properly catch any errors that occur in those callbacks.

Applied to files:

  • v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts
📚 Learning: 2024-09-30T06:13:46.595Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 3763
File: v3/examples/window/main.go:472-475
Timestamp: 2024-09-30T06:13:46.595Z
Learning: In `v3/examples/window/main.go`, `time.Sleep` is used within a goroutine and does not block the UI thread.

Applied to files:

  • v3/pkg/application/messageprocessor_dialog.go
📚 Learning: 2024-10-08T22:11:37.054Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 3763
File: v3/internal/commands/appimage_testfiles/main.go:295-299
Timestamp: 2024-10-08T22:11:37.054Z
Learning: In `v3/internal/commands/appimage_testfiles/main.go`, `time.Sleep` is used within a goroutine and does not block the UI thread.

Applied to files:

  • v3/pkg/application/messageprocessor_dialog.go
📚 Learning: 2025-01-18T21:19:47.778Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4024
File: v3/pkg/application/services.go:38-51
Timestamp: 2025-01-18T21:19:47.778Z
Learning: In the Wails v3 codebase, panic is used to catch invalid invocations that should never occur in production (programming errors), while error returns are reserved for recoverable error conditions (runtime errors). For example, the `NewService` function in `v3/pkg/application/services.go` uses panic to handle the case where more than one `ServiceOptions` instance is provided, as this is considered an unrecoverable programming error.

Applied to files:

  • v3/pkg/application/messageprocessor_dialog.go
📚 Learning: 2025-02-04T23:59:43.956Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4045
File: v3/internal/generator/render/info.go:28-68
Timestamp: 2025-02-04T23:59:43.956Z
Learning: In the Wails v3 project, internal functions are designed to panic on nil parameters as they represent contract violations, rather than adding defensive nil checks.

Applied to files:

  • v3/pkg/application/messageprocessor_dialog.go
📚 Learning: 2025-02-13T01:05:02.267Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4066
File: v3/pkg/application/messageprocessor_call.go:174-174
Timestamp: 2025-02-13T01:05:02.267Z
Learning: When handling JSON marshaling errors in Wails v3, the error message from json.Marshal provides sufficient debugging context. Logging raw data is unnecessary and could make logs harder to read.

Applied to files:

  • v3/pkg/application/messageprocessor_dialog.go
📚 Learning: 2025-08-08T13:15:20.339Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4484
File: v2/internal/frontend/utils/urlValidator.go:25-31
Timestamp: 2025-08-08T13:15:20.339Z
Learning: In Wails v2 (PR wailsapp/wails#4484), for BrowserOpenURL URL validation (v2/internal/frontend/utils/urlValidator.go), maintainers (APshenkin) prefer not to restrict schemes to an http/https allowlist because supported schemes may vary. The allowlist suggestion is declined; continue with the existing denylist approach and generic validation.

Applied to files:

  • v3/pkg/application/transport_http.go
📚 Learning: 2025-03-24T06:54:22.127Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications_windows.go:0-0
Timestamp: 2025-03-24T06:54:22.127Z
Learning: popaprozac prefers to focus on getting the Notifications API functionality working first and may consider code cleanup/refactoring for payload encoding logic in notifications_windows.go at a later time.

Applied to files:

  • v3/pkg/application/transport_http.go
📚 Learning: 2025-02-24T06:08:55.645Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications_windows.go:91-113
Timestamp: 2025-02-24T06:08:55.645Z
Learning: The JSON quote handling in Windows notifications' activation arguments (v3/pkg/services/notifications/notifications_windows.go) has a known limitation with single-quote collisions that needs to be addressed after initial testing.

Applied to files:

  • v3/pkg/application/transport_http.go
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.

Applied to files:

  • v3/examples/websocket-transport/transport_websocket.go
🧬 Code graph analysis (7)
v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)
v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (4)
  • Add (20-22)
  • Echo (29-31)
  • GetTime (37-39)
  • Greet (46-48)
v3/examples/websocket-transport/assets/websocket-transport.js (1)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
  • nanoid (16-16)
  • clientId (32-32)
v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts (1)
v3/internal/assetserver/bundledassets/runtime.debug.js (9)
  • running (2415-2415)
  • request (2414-2414)
  • id (65-65)
  • id (2411-2411)
  • result (525-525)
  • result (2175-2175)
  • result (2317-2317)
  • result (2404-2404)
  • result (2412-2412)
v3/pkg/application/messageprocessor_dialog.go (5)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/window.go (1)
  • Window (9-104)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/application/dialogs.go (3)
  • MessageDialogOptions (72-79)
  • OpenFileDialogOptions (169-187)
  • SaveFileDialogOptions (362-376)
v3/pkg/errs/error_functions.gen.go (2)
  • WrapInvalidDialogCallErrorf (183-194)
  • NewInvalidDialogCallErrorf (174-181)
v3/pkg/application/transport_event_ipc.go (2)
v3/pkg/application/application.go (1)
  • App (304-395)
v3/pkg/application/events.go (1)
  • CustomEvent (52-58)
v3/pkg/application/transport_http.go (4)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/pkg/errs/error_functions.gen.go (2)
  • WrapInvalidRuntimeCallErrorf (363-374)
  • NewInvalidRuntimeCallErrorf (354-361)
v3/pkg/application/bindings.go (1)
  • CallError (31-35)
v3/examples/websocket-transport/transport_websocket.go (3)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/events.go (1)
  • CustomEvent (52-58)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
🪛 Biome (2.1.2)
v3/internal/assetserver/bundledassets/runtime.js

[error] 1-1: This array contains an empty slots..

The presences of empty slots may cause incorrect information and might be a typo.
Unsafe fix: Replace hole with undefined

(lint/suspicious/noSparseArray)


[error] 1-1: Do not add then to a class.

(lint/suspicious/noThenProperty)


[error] 1-1: Shouldn't redeclare 'i'. Consider to delete it or rename it.

'i' is defined here:

(lint/suspicious/noRedeclare)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (2)
v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)

20-47: Bindings align with generated backend IDs.

These wrappers match the generated call IDs and keep the cancellable promise contract intact, so the frontend example stays in sync with the Go service.

v3/pkg/application/messageprocessor_dialog.go (1)

62-76: Buffered dialog response channel prevents deadlock.

Thanks for buffering the response channel and making the button callbacks non-blocking; this resolves the dialog hang we previously hit.

@leaanthony
Copy link
Member

This is an epic PR! I didn't realise you'd take on som many different issues in it 🚀 🎉 Please give me until the end of the weekend to review as it needs a solid look over.

It looks like there's a few merge conflicts. If they could be addressed that would be amazing 🙏

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
v3/internal/assetserver/bundledassets/runtime.js (1)

1-1: Consider generating bundled runtime at build time.

This minified bundle is checked into source control, which can make code reviews challenging and may lead to merge conflicts that are difficult to resolve. While there may be valid reasons for embedding this runtime (simplification, consistency), consider whether it would be better to:

  1. Keep only the source TypeScript/JavaScript files in the repository
  2. Generate this bundle during the build process
  3. Document the build steps clearly for contributors

This approach would make reviews more meaningful (reviewing source changes rather than minified output) and reduce the risk of the bundle getting out of sync with its source.

However, if embedding the pre-built runtime is intentional for the v3-alpha architecture, this can be addressed in a future iteration.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68965fd and 75ff8e2.

📒 Files selected for processing (5)
  • v3/examples/websocket-transport/assets/index.html (1 hunks)
  • v3/examples/websocket-transport/assets/websocket-transport.js (1 hunks)
  • v3/examples/websocket-transport/transport_websocket.go (1 hunks)
  • v3/internal/assetserver/bundledassets/runtime.js (1 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.

Applied to files:

  • v3/examples/websocket-transport/transport_websocket.go
📚 Learning: 2025-08-08T09:13:16.916Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).

Applied to files:

  • v3/examples/websocket-transport/transport_websocket.go
  • v3/examples/websocket-transport/assets/websocket-transport.js
🧬 Code graph analysis (3)
v3/examples/websocket-transport/transport_websocket.go (3)
v3/pkg/application/messageprocessor.go (2)
  • MessageProcessor (65-70)
  • RuntimeRequest (44-63)
v3/pkg/application/events.go (1)
  • CustomEvent (50-59)
v3/pkg/application/messageprocessor_args.go (1)
  • Args (8-10)
v3/examples/websocket-transport/assets/websocket-transport.js (1)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
  • nanoid (16-16)
  • clientId (32-32)
v3/internal/assetserver/bundledassets/runtime.js (1)
v3/examples/notifications/frontend/dist/assets/index-Dat4utuQ.js (4)
  • Be (6-6)
  • fe (1-1)
  • pe (1-1)
  • I (6-6)
🪛 Biome (2.1.2)
v3/internal/assetserver/bundledassets/runtime.js

[error] 1-1: This array contains an empty slots..

The presences of empty slots may cause incorrect information and might be a typo.
Unsafe fix: Replace hole with undefined

(lint/suspicious/noSparseArray)


[error] 1-1: Do not add then to a class.

(lint/suspicious/noThenProperty)


[error] 1-1: Shouldn't redeclare 'i'. Consider to delete it or rename it.

'i' is defined here:

(lint/suspicious/noRedeclare)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
🔇 Additional comments (4)
v3/examples/websocket-transport/assets/index.html (1)

237-357: LGTM!

The frontend implementation is well-structured with proper error handling, event listener setup, and UI wiring. The cache-busting approach and module imports work correctly for this example scenario.

v3/examples/websocket-transport/assets/websocket-transport.js (1)

30-246: LGTM!

The WebSocket transport implementation is solid. All the issues flagged in previous reviews have been properly addressed:

  • Connection state guards prevent race conditions
  • Message queue is cleared on disconnect
  • Falsy response values are handled correctly with ??
  • Event forwarding integrates cleanly with the Wails runtime
v3/examples/websocket-transport/transport_websocket.go (1)

72-88: LGTM on lifecycle and request handling!

The transport lifecycle, connection management, and request processing logic are well-implemented:

  • Proper initialization and shutdown sequencing
  • Context cancellation properly wired
  • Args are safely initialized to prevent nil panics (lines 193-195)
  • Response status defaults to 200 for success cases
  • Connection context flows through to the runtime handler

Also applies to: 92-115, 133-209, 212-253

v3/internal/assetserver/bundledassets/runtime.js (1)

1-1: No validation issues found—interface is properly documented and exported.

The RuntimeTransport interface is clearly defined, exported, and documented in v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts with JSDoc comments explaining the required .call() method signature. The codebase includes a working example in v3/examples/websocket-transport/ showing proper implementation.

The runtime implementation checks for null before invoking the transport (if (customTransport) { return customTransport.call(...) }) and relies on TypeScript's type system for compile-time safety. While the bundled JavaScript loses type information, this is expected and the documented interface pattern provides sufficient guidance for implementers.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
docs/src/content/docs/guides/custom-transport.mdx (1)

106-112: Appropriately cautions users but could strengthen security guidance.

The notes section responsibly mentions that the WebSocket example may need production hardening. However, consider expanding line 111 with specific guidance on what security aspects developers should address (e.g., authentication, encryption, origin validation).

  - You're responsible for error handling, reconnection logic, and security in your custom transport
+ - You're responsible for error handling, reconnection logic, and security in your custom transport (e.g., authentication, encryption, origin validation, rate limiting)
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 75ff8e2 and 116ec40.

📒 Files selected for processing (1)
  • docs/src/content/docs/guides/custom-transport.mdx (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
🔇 Additional comments (2)
docs/src/content/docs/guides/custom-transport.mdx (2)

8-85: Documentation structure and Go examples are clear and accurate.

The introduction, architecture diagram, and Go code examples properly reflect the Transport interface and application configuration changes introduced in this PR. The progression from interface definition to application wiring is logical and helpful.


87-104: TypeScript example is well-structured and appropriately addresses the typo fix.

The frontend modification example correctly shows usage of the setTransport() function and the custom RuntimeTransport interface. The TODO comment clearly indicates where implementation details go.

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
1 Security Hotspot
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@leaanthony
Copy link
Member

leaanthony commented Nov 17, 2025

This is looking really good. There was one thing I thought was worth discussing: you know how services can have a ServeHTTP method that can be used by frontend to retrieve files? I'm wondering if the transport interface could have something like Client() string and the runtime should/could fetch /wails/transport at init time to return whatever this method returns (if anything). We use this technique in services to call methods if they have been defined on the service. I was thinking this might be great to allow transports to provide Go config structs that would translate into dynamic frontend clients, like the address or port number could be set on the Go side. Ideally I'd like the developer to not need to worry about copy and pasting frontend transport code into their app.

Thoughts?

@APshenkin
Copy link
Contributor Author

@leaanthony oh, I didn't know that. Curious what are use-cases for it in services (why bindings are not enough).

Re Client() string I'm a bit confused by your proposal
It returns string, but then later you are saying great to allow transports to provide Go config structs

Should it be then Client() map[string]any ?

Also If I understood your idea correctly, then there is TransportHTTPHandler optional interface, that you can define to provide any possible routes if you need them under default webview assetHandler (and default http uses it). Wouldn't it be enough? As then me as transport developer I can put any routes that I want there, if needed.

For me this is not fully clean I'd like the developer to not need to worry about copy and pasting frontend transport code into their app. If I as a developer implement custom transport, it's highly likely that I will have to implement its parts for both frontend and backend. So not clear what exactly will be copy/pasted. Can you provide expanded example?

@atterpac
Copy link
Member

atterpac commented Nov 17, 2025

Curious what are use-cases for it in services (why bindings are not enough).

Think dynamic assets from v2 (outlined in tutorial here https://v3alpha.wails.io/tutorials/01-creating-a-service/#alternative-approach)

it allows you to have src=/some/route in html elements opposed to query and store then reference. Also allows for incremental implementation if you are migrating an existing web app you can mount your http service and it just works as a web app wrapper

Also If I understood your idea correctly, then there is TransportHTTPHandler optional interface, that you can define to provide any possible routes if you need them under default webview assetHandler (and default http uses it). Wouldn't it be enough? As then me as transport developer I can put any routes that I want there, if needed.

I haven't looked into the code fully I see it was based on my original work, there is a separate path for assets server that likely needs to be HTTP and I think the above comment could just attach to the asset server opposed to bindings transport

If I as a developer implement custom transport, it's highly likely that I will have to implement its parts for both frontend and backend

Agreed custom transport likely entails frontend and backend wiring

@APshenkin
Copy link
Contributor Author

@atterpac yes, this makes sence.

Re

there is a separate path for assets server that likely needs to be HTTP

It's still there. Optional interface AssetServerTransport with ServeAssets method

@leaanthony
Copy link
Member

leaanthony commented Nov 18, 2025

Yeah, it's hard to explain in text without diagrams but I'll try a use case:

So the websockets example has 2 parts: the Go side and the JS side. I imagine all transports will have both as the frontend needs some kind of logic to call the Go part.

By default, the HTTP transport is used for bindings so the JS side will have e.g. fetch + post etc.

For websockets this code needs changing to connect to a host+socket. This JS code needs running before we can call bindings so during init.

The question is whether we can fetch this JS from the backend during init rather than manually adjusting the frontend code so the host and port aren't defined in JS, but Go.

Let's imagine for a minute that when the runtime starts, and requests /wails/flags it also requests /wails/transport.js. For now, let's say that it assigns this JS file to window.transport and has all the code needed to connect, call, cancel etc over websocket. This is extremely similar to the ipc.js from v2. The runtime startup would be the same regardless of the transport implementation.

Now that we are always requesting this file, in the message handler we can request the result of this call from the Go implementation of the transport, which is what I meant by having a method like JSClient() string which in our example would return the JS websockets code.

This means that bindings transports can be completely self contained in a Go package. Let's take the example further:

import "github.com/org/repo/transports/websockets"

func main() {

// .....
app := application.New(.....
// .....
   Transport: websockets.New(websockets.Confg{
      Host: "1.2.3.4",
      Port: "8080",
      // More config
   },
//.....

Under the hood, the config is set in the implementation, the application starts up, runtime calls /wails/transport.js, message handler calls the interface method to get the JS client string,.returns it to frontend now frontend can connect to the websocket server, using the host and port from the Transport config.

This process would need to be synchronous at the start or we'd need some mechanism on the frontend to wait for that to happen if it's async via a callback or event but we'd need that anyway (what if the server is down?).

I hope that all makes sense!

@leaanthony
Copy link
Member

leaanthony commented Nov 19, 2025

As for the use cases in Services, think of anything that supports the service. There will be new docs uploaded soon and in that is a QR code generator tutorial. You add the service in Go, choose a route for it, then can request QR codes from the frontend using query Params, e.g. fetch('/services/qr?text=blah'). The speed is incredible. I hope that gives you some inspiration 😉

@APshenkin
Copy link
Contributor Author

@leaanthony ok, It seems I got it. Just to double check

You want to add method JSClient() string to transport that literally will return js code that will be returned when call /wails/transport.js ? Then in this code you would like to prepare the transport client and put it somewhere in global state, so that then wails runtime sdk will use this global state for doing calls. Proposal – put transport client in global.transport.

Am I right?

If so, I can try to play around it during the week

@leaanthony
Copy link
Member

I wasn't trying to be prescriptive though. I'm open to how it works, but the idea you could import a transport in Go, add it to your service and it just works sounds like amazing DX 😉 As for global on the frontend, it doesn't have to be, that was just an example. The idea is more that the runtime has a standard interface for making the calls and that gets fulfilled by whatever /wails/transport.js returns, which by default would be the standard http transport. Does that make sense?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Documentation Improvements or additions to documentation Linux MacOS runtime v3-alpha Windows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants