Skip to content

Forward-port @chipsenkbeil's RwLock window-map work onto current fix/refcell-panic (v2.11.1)#1

Closed
johncarmack1984 wants to merge 1 commit into
fix/refcell-panicfrom
john/rwlock-merge-2.11.1
Closed

Forward-port @chipsenkbeil's RwLock window-map work onto current fix/refcell-panic (v2.11.1)#1
johncarmack1984 wants to merge 1 commit into
fix/refcell-panicfrom
john/rwlock-merge-2.11.1

Conversation

@johncarmack1984
Copy link
Copy Markdown
Collaborator

@johncarmack1984 johncarmack1984 commented May 8, 2026

No description provided.

Forward-port of @chipsenkbeil's chip/borrow-tracing--rwlock work
(2026-02, 10 commits on top of dev) onto current fix/refcell-panic
HEAD (which now includes the v2.11.1 merge). The original branch
chip/borrow-tracing--rwlock @ 1485b29 stays preserved upstream.

The structural divergence between Chip's branch and current
fix/refcell-panic was significant -- v2.11.1 extracted WindowsStore
from inline-in-lib.rs into its own windows_store.rs module with a
closure-based borrow API (`store(|map| ...)`, `window(id, |w| ...)`),
which itself addresses the synchronous-borrow-conflict failure mode
that motivated Chip's RwLock work. So this isn't a mechanical replay
of the squashed commits -- it's a port that keeps Chip's intent
(replace RefCell with RwLock + add tracing-borrows feature) under the
new closure-based API.

Changes vs fix/refcell-panic:
- crates/tauri-runtime-wry/Cargo.toml: new `tracing-borrows` cargo
  feature (depends on `tracing`).
- crates/tauri/Cargo.toml: pass `tracing-borrows` through to
  tauri-runtime-wry's optional dep.
- crates/tauri-runtime-wry/src/windows_store.rs: replace
  `RefCell<WindowMap>` with `RwLock<WindowMap>`. The closure-based
  public API (`store`, `store_mut`, `window`, `window_mut`, `insert`,
  `remove`) is preserved. Borrow failures now surface as
  `Error::Borrow(LockKind)` (lock contention) or
  `Error::Poisoned(LockKind)` (panic-during-write); the previous
  `BorrowError`/`BorrowMutError` carried no distinguishing payload, so
  the new variants are strictly more informative. With
  `tracing-borrows` enabled, every borrow logs file:line:column +
  thread id at trace level for diagnosis.

Squashed from (preserved on chip/borrow-tracing--rwlock):
  1fc81a9 add tracing to wry runtime borrows
  9f92638 cargo +nightly fmt
  d468547 remove file trace
  0657afd flush stdout before borrows
  ca26385 Revert "flush stdout before borrows"
  0de878f separate tracing from tracing borrows
  6a13e7b add optional tracing dependency when just borrows
  27d550d enable tracing-borrows on runtime by default
  528aa9b add thread id (debug format)
  1485b29 replace window map refcell with rwlock
@johncarmack1984 johncarmack1984 marked this pull request as ready for review May 8, 2026 16:02
johncarmack1984 added a commit that referenced this pull request May 26, 2026
Script #1 (`isTauri` + `__TAURI_INTERNALS__` setup) is registered via
`AddScriptToExecuteOnDocumentCreated` and, per wry 0.51+ behavior, fires
on every document creation -- main frame AND every subframe -- on
WebView2.

The original ordering put the non-configurable `isTauri`
defineProperty first. If the script ran a second time in the same JS
context (e.g. a reload, an HMR-induced subframe re-creation, or any
WebView2-internal document re-entry), that first call threw
`TypeError: Cannot redefine property: isTauri`, which short-circuited
the rest of the function and left `__TAURI_INTERNALS__` undefined for
later init scripts like `path/init.js`. Symptom: "Cannot read
properties of undefined (reading 'plugins')" at
`Object.defineProperty(window.__TAURI_INTERNALS__.plugins, 'path', ...)`.

Reorder so `__TAURI_INTERNALS__` is established first, and wrap the
`isTauri` define in a try/catch so a re-entry never strands the rest
of init.
johncarmack1984 added a commit that referenced this pull request May 26, 2026
…LS__

The Script #1 reorder/idempotency change in cdffdc0 was insufficient:
something in the WebView2 init path leaves `__TAURI_INTERNALS__` undefined
in the isolation iframe even when Script #1 should have established it.
The visible symptom is path/init.js (the first plugin init to access
`__TAURI_INTERNALS__.plugins`) throwing "Cannot read properties of
undefined (reading 'plugins')".

Plugin init scripts only ever attach plugin-side helpers to
`__TAURI_INTERNALS__.plugins`. The isolation iframe does not consume
those helpers -- it only forwards IPC via postMessage + AES-GCM. So
skipping plugin init when `__TAURI_INTERNALS__` is missing is correct
semantically, not just defensive.

Inject `if (!window.__TAURI_INTERNALS__) return;` into the IIFE wrapper
in `PluginStore::initialization_script`, which covers all plugin init
scripts (built-in path plugin + any external plugin that registers via
`Builder::js_init_script`) in one place.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant