Skip to content

[V3] Refactor binding transport layer - #4702

Merged
leaanthony merged 38 commits into
wailsapp:v3-alphafrom
APshenkin:v3/trasport-layer
Dec 7, 2025
Merged

leaanthony merged 38 commits into
wailsapp:v3-alphafrom
APshenkin:v3/trasport-layer

Conversation

@APshenkin

@APshenkin APshenkin commented Nov 10, 2025 •

Copy link
Copy Markdown
Contributor

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

    • Support for pluggable IPC transports (e.g., WebSocket) and a WebSocket example with a working frontend demo.
    • Public runtime gains APIs to set/get a custom transport at runtime.
  • Refactor

    • Core runtime and message processing refactored to use request-driven transport plumbing and extensible transport interfaces.
    • IPC/event delivery auto-wired via transport implementations.
  • New Utilities

    • Introduced structured error utilities for clearer error types and wrapping.
  • Documentation

    • Guide added for creating custom transports.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Nov 10, 2025 •

Copy link
Copy Markdown
Contributor

Walkthrough

Introduces a pluggable IPC transport layer (Transport interfaces, HTTP and WebSocket transports), refactors runtime and message processing from HTTP-centric handlers to a RuntimeRequest-driven model, adds a typed errs package with codegen, and includes a WebSocket transport example with generated frontend bindings and runtime API changes.

Changes

Cohort / File(s) Summary
Dependency Updates
v3/go.mod, v3/examples/*/go.mod, v3/tests/*/go.mod
Removed indirect github.com/pkg/errors v0.9.1, bumped github.com/wailsapp/go-webview2 to v1.0.22 across examples, added github.com/gorilla/websocket v1.5.3 to main module.
Transport Abstraction & Implementations
v3/pkg/application/transport.go, v3/pkg/application/transport_http.go, v3/pkg/application/transport_event_ipc.go, v3/examples/websocket-transport/transport_websocket.go
Added a public Transport interface, HTTPTransport implementation, EventIPCTransport, and a WebSocket transport example implementation.
Application Startup & Options
v3/pkg/application/application_options.go, v3/pkg/application/application.go
Added Transport field to Options and rewired application startup to initialize and manage the configured transport, serve assets via transport, and wire event delivery.
Message Processing Refactor
v3/pkg/application/messageprocessor.go, v3/pkg/application/messageprocessor_*.go, v3/pkg/application/messageprocessor_args.go, (removed) v3/pkg/application/messageprocessor_params.go
Replaced HTTP writer-based handlers with a request-driven API using RuntimeRequest and Args; converted many process* methods to return (any, error); removed old QueryParams/Args file and added a new Args/MapArgs implementation.
Runtime API & Bundles
v3/internal/runtime/.../runtime.ts, v3/internal/runtime/.../calls.ts, v3/internal/runtime/.../dialogs.ts, v3/internal/assetserver/bundledassets/runtime.js, v3/internal/runtime/runtime.go
Added RuntimeTransport interface and setTransport/getTransport, updated runtime call path to prefer custom transport (fallback to HTTP), adjusted runtime bundle exports, and changed Core to accept flags.
WebSocket Example & Frontend Bindings
v3/examples/websocket-transport/* (Go: main.go, GreetService.go, transport; JS: websocket-transport.js, assets, generated bindings and index.js, README.md, assets/index.html)
Added complete WebSocket transport example: backend service, server setup, client transport JS, generated bindings (greetservice.js, index.js), HTML demo, and README documenting usage.
Error Framework (errs)
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
New errs package with ErrorType constants, WailsError interface, utilities (Is/Cause/Has), and code-generated typed constructors/wrappers for categorized errors.
Event & Window Changes
v3/pkg/application/event_manager.go, v3/pkg/application/webview_window*.go, v3/pkg/application/window.go
EventManager dispatch simplified (removed per-window pre-dispatch), removed callback-style window JS response helpers (CallResponse/CallError/DialogResponse/DialogError) and Callback interface; runtime.Core calls updated to pass flags.
Asset Server & Bundling
v3/internal/assetserver/...
Moved runtime/transport serving into transport-driven middleware; runtime bundle export mappings adjusted to expose transport helpers and objectNames/clientId.
Docs & Changelog
docs/src/content/docs/guides/custom-transport.mdx, v3/UNRELEASED_CHANGELOG.md
New guide for custom transports and changelog entry.
Small Example Dependency Files
v3/examples/*/go.mod
Adjusted example go.mod files to reflect dependency changes (webview2 bumped, pkg/errors removed).

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant FE as Frontend (runtime.ts / JS)
    participant RT as Runtime API (runtime.ts)
    participant TR as Transport (HTTPTransport / WebSocketTransport)
    participant MP as MessageProcessor (server)
    participant APP as App handlers (process* methods)

    FE->>RT: call(object, method, args)
    RT->>RT: if customTransport set?
    alt custom transport available
        RT->>TR: transport.call(object, method, window, args)
    else
        RT->>TR: HTTP POST /wails/runtime (default transport)
    end
    TR->>MP: HandleRuntimeCallWithIDs(ctx, RuntimeRequest)
    MP->>APP: route by object -> processX(req)
    APP-->>MP: (result, error)
    MP-->>TR: response payload / error
    TR-->>RT: transport response
    RT-->>FE: resolve promise (result or error)
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~150 minutes

  • Areas requiring extra attention:
    • Message processor refactor (many files): ensure consistent use of RuntimeRequest/Args and correct error wrapping with errs.
    • Transport lifecycle and asset-serving integration (application.go, transport_*.go): verify Start/Stop, ServeAssets, middleware ordering, and event wiring.
    • Runtime transport switching (runtime.ts, bundled runtime.js, calls.ts): confirm fallback behavior, headers, and content-type handling.
    • Error framework usage: ensure all new errs constructors/wrappers are used consistently and that error chains preserve causes.
    • Removal of window callback methods: check for remaining call sites and JS expectations (generated bindings/runtime behavior).

Possibly related PRs

Suggested labels

Enhancement, bindings, go, size:XXL, lgtm

Poem

🐇 A tiny rabbit hops on code so new,

Transports unbound — WebSocket sings through.
Errors now typed, requests flow neat and clear,
Flags in the core, bindings whisper near.
Hooray — pluggable paths for apps to steer!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.20% 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' clearly and concisely summarizes the primary change: refactoring the transport layer for bindings with a focus on Transport abstraction.
Description check ✅ Passed The PR description covers the main changes, motivation, and includes references to related issues, but is missing some checklist items and didn't update the changelog. However, the core content is substantial and mostly complete.
✨ 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 9c93025 and 747bc95.

⛔ Files ignored due to path filters (1)
  • v3/go.sum is excluded by !**/*.sum
📒 Files selected for processing (1)
  • v3/go.mod (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • v3/go.mod
⏰ 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

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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.

Comment thread v3/pkg/application/application.go Resolved
Comment thread v3/pkg/application/transport_http.go Resolved
Comment thread v3/pkg/application/transport_http.go Resolved
Comment thread v3/pkg/errs/error_functions.gen.go Resolved
Comment thread v3/pkg/errs/utils.go Resolved

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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.

Comment thread v3/examples/websocket-transport/main.go Resolved
Comment thread v3/pkg/application/messageprocessor.go Resolved
Comment thread v3/pkg/application/transport_http.go Resolved
Comment thread v3/pkg/application/transport_http.go Resolved
Comment thread v3/pkg/application/transport.go Resolved
Comment thread v3/pkg/errs/utils.go Resolved

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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

Comment thread v3/pkg/application/CUSTOM_TRANSPORT.md Resolved
Comment thread v3/pkg/application/transport_http.go Resolved
Comment thread v3/pkg/application/transport_http.go Resolved

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 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 fa62058 and 4e393f5.

📒 Files selected for processing (1)
  • v3/UNRELEASED_CHANGELOG.md (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). (4)
  • 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)
  • GitHub Check: semgrep-cloud-platform/scan

Comment thread v3/UNRELEASED_CHANGELOG.md Resolved
@APshenkin

Copy link
Copy Markdown
Contributor Author

@leaanthony I spent some time looking into this option, and my personal opinion is that we should keep things as they are.

Adding JSClient would just introduce another way to solve the same task without providing clear benefits.

We can already pass any “args” or “transport params” through Flags. And if someone wants to serve a client from the transport layer, TransportHTTPHandler already allows adding custom routes.

I experimented with this in a separate branch — you can see the examples in this PR: https://github.com/APshenkin/wails/pull/2/files

Practically speaking, if I were implementing a custom transport for an app, I’d build it together with the app using the same tooling. Creating a separate /wails/transport.js would require an additional build pipeline just to serve that file from /wails/transport.js.

What do you think?

@leaanthony

Copy link
Copy Markdown
Member

@APshenkin - thanks for taking the time to look at that. I appreciate your efforts 🙏 I think there may be some cross-wires here though. Perhaps it would be easier for me to ask a question: If someone wanted to reuse the websocket transport (or any transport) in their project, how would they do that?

@APshenkin

Copy link
Copy Markdown
Contributor Author

@leaanthony
If you want provide transport as a library/package, you can then:
Few options:

  1. go module + npm package – might suit for cases, where app fetches static from external resource
  2. go module + serving required js via TransportHTTPHandler + adding await import(/whatever-path-you-specified-in-TransportHTTPHandler.js); to your app

or simplest – copy it in your project

@APshenkin

Copy link
Copy Markdown
Contributor Author

@leaanthony anything that blocks us to merge this PR? Happy to work on it.

if you still want to add JSClient, can do so, as heavy lifting for it is very low.

@leaanthony

Copy link
Copy Markdown
Member

@APshenkin thanks for your patience. I wanted to try and review the last files. It mainly looks good to me and thanks again for taking on such an epic PR 🙏

The thing I was trying to convey before was whether this code:

const { setTransport } = await import('/wails/runtime.js');

class MyRuntimeTransport {
  call(objectID: number, method: number, windowName: string, args: any): Promise<any> {
    // TODO: implement IPC call with your transport protocol

    return resp;
  }
}

const myTransport = new MyRuntimeTransport();
setTransport(myTransport);

could be automatic instead of something that people will need to copy and paste in. Like this could be in the runtime by default:

let transport = await fetch("/wails/transport")
setTransport(transport)

Which means your transport module would be able to service the frontend dynamically by handling /wails/transport (via message handler and forwarded to the transport implementation), meaning it could be entirely configurable in Go and there would be no need to update JS (most people won't care).

Does this make any sense? It's been a loooong day 😅

@APshenkin

Copy link
Copy Markdown
Contributor Author

@leaanthony added. Tell what you think about it

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (3)
v3/examples/websocket-transport/assets/index.html (2)

328-340: setInterval created on line 331 is never cleared, causing a potential memory leak.

The status polling interval runs indefinitely even after the module/page unloads. For a long-running app or single-page app with navigation, this will accumulate intervals.

Store the interval ID and clear it when the transport is destroyed or the page unloads:

-    function updateConnectionStatus() {
-      const statusEl = document.getElementById("connection-status");
-
-      setInterval(() => {
+    function updateConnectionStatus() {
+      const statusEl = document.getElementById("connection-status");
+      const intervalId = setInterval(() => {
         if (transport.isConnected()) {
           statusEl.innerHTML = "<span class=\"status connected\">✓ Connected to WebSocket (ws://localhost:9099)</span>";
         } else {
           statusEl.innerHTML = "<span class=\"status disconnected\">✗ Disconnected</span>";
         }
       }, 1000);
+      
+      // Cleanup on page unload
+      window.addEventListener("beforeunload", () => clearInterval(intervalId));
     }

169-169: Hardcoded WebSocket endpoint in display text may become stale.

The info text on line 169 hardcodes ws://localhost:9099/wails/ws. If the transport or port changes, this text requires manual updates. Consider extracting the endpoint from the transport object or documenting it prominently.

Derive the endpoint from the transport object at runtime (if the transport exposes it):

-      instead of the default HTTP fetch-based transport. All Wails <strong>generated bindings</strong> work identically!
+      instead of the default HTTP fetch-based transport. All Wails <strong>generated bindings</strong> work identically!<br>
+      <span id="endpointDisplay"></span>

Then, after importing the transport, populate the endpoint dynamically (if available on the transport object).

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

114-121: Use field names in Args composite literal for robustness.

Args currently has a single unexported field (rawData), but the literal &Args{body.Args} depends on field order. This is fragile if Args ever gains additional fields.

Prefer a field‑named literal to make the intent explicit and future‑proof:

-		Args:              &Args{body.Args},
+		Args:              &Args{rawData: body.Args},
📜 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 4e393f5 and 9c93025.

📒 Files selected for processing (6)
  • v3/examples/websocket-transport/assets/index.html (1 hunks)
  • v3/examples/websocket-transport/transport_websocket.go (1 hunks)
  • v3/examples/websocket-transport/websocket-transport.js (1 hunks)
  • v3/pkg/application/application.go (2 hunks)
  • v3/pkg/application/transport.go (1 hunks)
  • v3/pkg/application/transport_http.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • v3/examples/websocket-transport/transport_websocket.go
  • v3/pkg/application/transport.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-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
📚 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-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-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/websocket-transport.js
🧬 Code graph analysis (2)
v3/pkg/application/application.go (6)
v3/pkg/application/transport.go (2)
  • Transport (18-28)
  • TransportHTTPHandler (65-67)
v3/pkg/application/transport_http.go (2)
  • NewHTTPTransport (20-31)
  • HTTPTransportWithLogger (37-41)
v3/pkg/application/transport_event_ipc.go (1)
  • EventIPCTransport (3-5)
v3/internal/assetserver/middleware.go (2)
  • Middleware (10-10)
  • ChainMiddleware (13-20)
v3/internal/assetserver/common.go (1)
  • ServeFile (29-40)
v3/internal/assetserver/options.go (1)
  • Options (10-29)
v3/pkg/application/transport_http.go (3)
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)
⏰ 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 (ubuntu-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (3)
v3/examples/websocket-transport/assets/index.html (1)

237-251: Transport and runtime initialization follows new abstraction pattern correctly.

The cache-buster on line 241 and proper error boundary on lines 238–350 are good practices for an example. The transport-to-runtime wiring via setTransport() aligns well with the PR's pluggable transport design.

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

82-105: Avoid auto‑reconnect after an explicit close() call.

ws.onclose always schedules a reconnect, even when the connection was closed intentionally via close(). This makes it impossible for callers (or the runtime) to reliably shut down the transport; a manual close just triggers the reconnect loop again.

Consider tracking manual closes and skipping reconnect in that case, for example:

 export class WebSocketTransport {
   constructor(url, options = {}) {
     this.url = url;
     this.ws = null;
     this.wsReady = false;
     this.pendingRequests = new Map();
     this.messageQueue = [];
     this.reconnectTimer = null;
+    this.manualClose = false;
@@
   close() {
-    if (this.reconnectTimer) {
-      clearTimeout(this.reconnectTimer);
-      this.reconnectTimer = null;
-    }
-
-    if (this.ws) {
-      this.ws.close();
-      this.ws = null;
-    }
-
-    this.wsReady = false;
+    this.manualClose = true;
+    if (this.reconnectTimer) {
+      clearTimeout(this.reconnectTimer);
+      this.reconnectTimer = null;
+    }
+    if (this.ws) {
+      this.ws.close();
+      this.ws = null;
+    }
+    this.wsReady = false;
   }
@@
       this.ws.onclose = () => {
         console.log("[WebSocket] Disconnected");
         this.wsReady = false;
@@
-        // Attempt to reconnect
-        if (!this.reconnectTimer) {
+        if (this.manualClose) {
+          // One-shot: don't reconnect after an explicit close.
+          this.manualClose = false;
+          return;
+        }
+
+        // Attempt to reconnect after unexpected disconnects
+        if (!this.reconnectTimer) {
           this.reconnectTimer = setTimeout(() => {
             this.reconnectTimer = null;
             console.log("[WebSocket] Attempting to reconnect...");
             this.connect().catch(err => {
               console.error("[WebSocket] Reconnection failed:", err);
             });
           }, this.reconnectDelay);
         }
       };

Also applies to: 213-225

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

82-99: Preserve OnShutdown callback ordering (user hook first, then transport stop).

cleanup() runs shutdownTasks in the order they were added, and the comment on shutdownTasks says the application option OnShutdown runs first. Currently:

  • The transport stop hook is added via result.OnShutdown(func() { transport.Stop() }) (Line 93).
  • The user‑supplied appOptions.OnShutdown hook is added later (Lines 176–178).

This inverts the documented order and means user OnShutdown now runs after the transport has been stopped, which can surprise apps that want to interact with the transport/runtime during shutdown.

Consider registering the user hook before the transport stop hook:

-	// Register shutdown task to stop transport
-	result.OnShutdown(func() {
-		if err := transport.Stop(); err != nil {
-			result.error("failed to stop custom transport: %w", err)
-		}
-	})
@@
-	if appOptions.OnShutdown != nil {
-		result.OnShutdown(appOptions.OnShutdown)
-	}
+	if appOptions.OnShutdown != nil {
+		result.OnShutdown(appOptions.OnShutdown)
+	}
+
+	// Register shutdown task to stop transport after user hook
+	result.OnShutdown(func() {
+		if err := transport.Stop(); err != nil {
+			result.error("failed to stop custom transport: %w", err)
+		}
+	})

This keeps the documented contract and gives user shutdown logic access to a still‑running transport.

Comment thread v3/pkg/application/transport_http.go Resolved
@APshenkin

Copy link
Copy Markdown
Contributor Author

@leaanthony did you had a chance to take a look? Anything that I can help with this PR

@sonarqubecloud

sonarqubecloud Bot commented Dec 7, 2025

Copy link
Copy Markdown

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
Copy Markdown
Member

@APshenkin - Thanks for your patience. I'm good for this to go as is. I think there might be some tweaks but that can come later and definitely don't want to block such an epic PR 👍 🙏

@leaanthony
leaanthony merged commit 561473d into wailsapp:v3-alpha Dec 7, 2025
47 of 49 checks passed
leaanthony added a commit that referenced this pull request Dec 10, 2025
This commit integrates iOS platform support for Wails v3, adapting the
iOS-specific code to work with the new transport layer architecture.

Key changes:
- Add iOS-specific application, webview, and runtime files
- Add iOS event types and processing
- Add iOS examples and templates
- Update messageprocessor to handle iOS requests
- Move badge_ios.go to dock package

Note: The iOS branch was based on an older v3-alpha and required
significant conflict resolution due to the transport layer refactor
(PR #4702). Some iOS-specific code may need further adaptation:
- processIOSMethod needs to be implemented with new RuntimeRequest signature
- iOS event generation in tasks/events/generate.go needs updating

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai coderabbitai Bot mentioned this pull request Feb 11, 2026
2 of 15 tasks
Grantmartin2002 pushed a commit to Grantmartin2002/wails that referenced this pull request Apr 29, 2026
* custom transport initial

* transport codecs

* runtime set transport

* events transport

* clauded example

* bundled runtime

* wip: transport

* rework transports

* rework dialog responses

* cleanup

* cleanup

* improve error handling in HTTPTransport

* cleanup

* cleanup

* cleanup

* cleanup

* review changes

* review changes

* review changes

* review changes

* review changes

* review changes

* review changes

* move documentation to website docs

* update doc

* update changelog

* introduce JSClient method for transport for embedding JS part in transport

---------

Co-authored-by: Atterpac <Capretta.Michael@gmail.com>
Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
Grantmartin2002 pushed a commit to Grantmartin2002/wails that referenced this pull request Apr 29, 2026
This commit integrates iOS platform support for Wails v3, adapting the
iOS-specific code to work with the new transport layer architecture.

Key changes:
- Add iOS-specific application, webview, and runtime files
- Add iOS event types and processing
- Add iOS examples and templates
- Update messageprocessor to handle iOS requests
- Move badge_ios.go to dock package

Note: The iOS branch was based on an older v3-alpha and required
significant conflict resolution due to the transport layer refactor
(PR wailsapp#4702). Some iOS-specific code may need further adaptation:
- processIOSMethod needs to be implemented with new RuntimeRequest signature
- iOS event generation in tasks/events/generate.go needs updating

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@taliesin-ai taliesin-ai added v3 and removed v3-alpha labels Aug 9, 2026
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 Windows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants