Skip to content

Fix native-window config delivery on lazy-load + add debug surface - #47

Merged
epeicher merged 7 commits into
trunkfrom
fix/native-window-config-delivery
Apr 30, 2026
Merged

Fix native-window config delivery on lazy-load + add debug surface#47
epeicher merged 7 commits into
trunkfrom
fix/native-window-config-delivery

Conversation

@epeicher

@epeicher epeicher commented Apr 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes the historical mid-session-activation bug where a native-window bundle's wp_localize_script / wp_add_inline_script data could be silently dropped, plus the related DX gaps surfaced in the cron-manager externalization retro.

  • Structural fix: loadVendorScript now injects each handle's harvested extra data (scriptL10n / scriptBefore / scriptAfter / scriptTranslations) inline alongside the lazy <script src> tag, in wp_print_scripts order. Applied to every lazy-load consumer (native-windows, widgets, wallpapers, commands, settings-tabs, title-bar-buttons).
  • Discoverable config delivery: new 'config' => array(…) arg on desktop_mode_register_window(), read in JS via wp.desktop.getWindowConfig( id ). Lands on both eager and lazy paths.
  • Debug surface: wp.desktop.debug.window( id ) reports { scriptHandle, scriptUrl, loadPath: 'eager'|'lazy'|'unknown', tagInDom, configPresent, extras: { … } }. Read-only.
  • Version stamping: desktop.{js,min.js}, iframe-bridge.{js,min.js}, code-editor.{js,min.js} now use filemtime so identical ?ver= never serves different bytes.
  • Sharper recycle-bin error message that distinguishes "loaded outside of desktop mode" (consumer misuse) from "config did not reach the page" (integration contract failure).
  • Docs: new examples/window-with-config.md, updates to architecture.md, native-windows-proposal.md, javascript-reference.md, examples index, AGENTS.md doc-tree.

After this lands, the cron-manager plugin can drop its admin-ajax.php bundle workaround and use the supported 'config' arg.

Renames desktop_mode_resolve_script_url()desktop_mode_resolve_script_payload(). No external consumers; no back-compat shim (per YOLO mode).

Background

Reported in DX retro at ~/Desktop/desktop-mode-DX-report.md. Root cause: the lazy-load path appends a raw <script src=…> and never invokes wp_print_scripts(), so any wp_localize_script / wp_add_inline_script / wp_set_script_translations data attached to the registered handle was silently dropped on mid-session plugin activation. The script tag worked; only the inline data was lost.

Test plan

  • npm run build (all 4 bundles)
  • npm run lint
  • ./node_modules/.bin/tsc --noEmit
  • npm run test:js (602 / 602 passing)
  • Manual smoke: install a sibling plugin that calls desktop_mode_register_window with 'config', read wp.desktop.getWindowConfig() from its bundle, verify wp.desktop.debug.window() reports loadPath correctly on both fresh-page-load (eager) and live activation (lazy).
  • Manual smoke: confirm cron-manager (or any plugin using wp_localize_script on its native-window handle) now works on live-activation without the admin-ajax workaround.
Open WordPress Playground Preview

`?ver=` now changes whenever the bytes change, so identical query
strings can no longer serve different bytes between sessions.
Recycle-bin rest config error now blames the integration contract
(config did not reach the page) instead of the consumer (loaded
outside of desktop mode), pointing at the new docs example.
Replaces desktop_mode_resolve_script_url() with
desktop_mode_resolve_script_payload() which captures the registered
handle's wp_localize_script / wp_add_inline_script / wp_set_script_translations
data alongside the URL. Every payload builder that powers a lazy-load
path (native-windows, widgets, wallpapers, commands, settings-tabs,
title-bar-buttons) now ships scriptBefore / scriptAfter / scriptL10n
/ scriptTranslations so the shell can re-inject what wp_print_scripts
would have, fixing the silent-config-loss bug on mid-session plugin
activation.

Adds 'config' arg to desktop_mode_register_window() — discoverable
alternative to wp_localize_script, delivered through both eager and
lazy paths via wp.desktop.getWindowConfig(id).
loadVendorScript now accepts a ScriptExtras bag and injects
translations / l10n / before snippets as inline <script> tags before
the src tag, and the after snippet after the src load event fires —
mirroring wp_print_scripts ordering. Every server-sync consumer
forwards the harvested extras from the payload, so wp_localize_script
and wp_add_inline_script data on lazy-loaded handles is no longer
silently dropped.

This is the structural fix for the cron-manager class of integration
bug: any plugin calling wp_localize_script on its native-window
script handle now Just Works on both the eager and lazy load paths.
getWindowConfig(id) reads the bundle-bound config blob shipped by
desktop_mode_register_window's new 'config' arg. The
wp.desktop.debug.window(id) surface answers the canonical "what
state does the framework think my native window is in?" question:
script handle, URL, eager-vs-lazy load path, whether the script tag
is in the DOM, whether the config global is set, and the harvested
extras count. Read-only — turns the previous 9-iteration debugging
session into a one-liner.

Updates commands-server-sync test for the new loadVendorScript
signature; rebuilds recycle-bin bundle for the sharper config error.
- New examples/window-with-config.md — recommended recipe for shipping
  session-bound data (REST URLs, nonces) to a native-window bundle
  via the new 'config' arg.
- architecture.md gains an "eager vs lazy script load" subsection
  explaining the wp_print_scripts bypass and how the harvested extras
  + 'config' arg make both paths Just Work.
- native-windows-proposal.md gains a "shipping config to the bundle"
  block.
- javascript-reference.md documents wp.desktop.getWindowConfig() and
  wp.desktop.debug.window().
- examples/README.md + examples/native-windows.md cross-reference.
- AGENTS.md doc-tree updated.
…nfig-delivery

# Conflicts:
#	assets/js/recycle-bin.js
#	assets/js/recycle-bin.min.js
PR #48 added four new lazy-load consumers (window themes / controls /
slots / custom chrome) using the same loadVendorScript( scriptUrl )
pattern. Without this change, any wp_localize_script /
wp_add_inline_script data attached to those handles would be silently
dropped on mid-session activation — the same class of bug Phase 2
fixed for the original five surfaces.

- includes/window-chrome.php: 8 callsites switched from
  desktop_mode_resolve_script_url to desktop_mode_resolve_script_payload,
  shipping scriptBefore / scriptAfter / scriptL10n / scriptTranslations
  on each script + metadata payload entry.
- src/types.ts: 8 ServerEntry types extended with optional extras fields.
- src/window-chrome/{themes,controls,slots,chrome}/server-sync.ts:
  forward the harvested extras to loadVendorScript.
@epeicher
epeicher merged commit 94c4a52 into trunk Apr 30, 2026
15 checks passed
@epeicher
epeicher deleted the fix/native-window-config-delivery branch April 30, 2026 15:43
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