From 4e3208430ae719009339c639f4ea1a894980baf7 Mon Sep 17 00:00:00 2001 From: Roberto Aranda Date: Tue, 15 Sep 2026 17:14:52 +0200 Subject: [PATCH] Lazy scripts: replay a bundle's declared dependencies on live activation A bundle the shell fetches lazily never went through WordPress's own dependency resolution, and the payload resolver dropped any handle without a src. A plugin whose config rides a src-less alias handle declared as its bundle's dependency (AllTerrain Forms) therefore opened, after a live activation, with the config undefined. Every lazy payload builder now ships the handle's dependency closure; native windows carry it as `deps` inside the handle-keyed script-data map. The loader replays an alias's inline data in print order, once per document, and recognises Core's printed tag ids so a dependency the page already has is never run twice. --- docs/architecture.md | 2 +- docs/hooks-reference.md | 2 +- docs/javascript-reference.md | 2 +- docs/migration-wp-package-globals.md | 40 ++++-- includes/commands.php | 6 + includes/core/payload.php | 118 +++++++++++++----- includes/desktop-files/openers.php | 3 + includes/desktop-files/registry.php | 3 + includes/dock-rail-renderer.php | 3 + includes/games/registry.php | 3 + includes/registries/wallpapers.php | 3 + includes/settings-tabs.php | 6 + includes/title-bar-buttons.php | 3 + includes/unfocus-effects.php | 3 + includes/window-actions.php | 3 + includes/window-chrome.php | 24 ++++ includes/window-links.php | 3 + src/commands/server-sync.ts | 3 + src/dock-rail/server-sync.ts | 3 + src/effects/server-sync.ts | 3 + src/games/launch.ts | 6 +- src/games/server-sync.ts | 1 + src/games/types.ts | 4 + src/native-windows.ts | 39 ++++++ src/script-presence.ts | 53 +++++++- src/settings/server-sync.ts | 3 + src/title-bar-buttons/server-sync.ts | 3 + src/types.ts | 113 ++++++++++++++--- src/wallpapers/lazy.ts | 3 + src/wallpapers/vendor-loader.ts | 53 +++++++- src/window-actions/server-sync.ts | 3 + src/window-chrome/chrome/server-sync.ts | 3 + src/window-chrome/controls/server-sync.ts | 3 + src/window-chrome/slots/server-sync.ts | 3 + src/window-chrome/themes/server-sync.ts | 3 + src/window-links/server-sync.ts | 3 + tests/phpunit/tests/commands.php | 36 ++++++ .../phpunit/tests/nativeWindowLazyScript.php | 78 ++++++++++++ .../tests/resolveScriptDependencies.php | 63 ++++++++++ tests/vitest/commands-server-sync.test.ts | 20 +++ .../vitest/native-windows-lazy-script.test.ts | 93 ++++++++++++++ tests/vitest/script-presence.test.ts | 55 ++++++++ tests/vitest/vendor-loader.test.ts | 104 +++++++++++++++ 43 files changed, 914 insertions(+), 67 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index 071d5c8f8..996b0997a 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -241,7 +241,7 @@ Three related knobs: Shell surfaces that render on demand but are **not** native windows — the AI assistant, the bug-report window — get the same deferral through a different pipe: `openstation_build_deferred_styles()` resolves their handles into `openStationConfig.deferredStyles` (handle → `{ url, inline }`), and the surface's open path calls `ensureDeferredStyle( handle )` (`src/deferred-styles.ts`) to inject the sheet once, in parallel with whatever bundle the open is already fetching. Internal plumbing rather than public API — a plugin's own on-demand surface should be a native window and use `styles`. - **`wp.os.loadWindowScript( id )`** — load a window's bundle without opening the window, for the case where another bundle needs an API that one publishes. See [`javascript-reference.md`](./javascript-reference.md). -The payload builders harvest each registered handle's `extra['data']` (localize), `extra['before']` / `extra['after']` (inline), and `wp_set_script_translations()` snippet into a **handle-keyed map** — `nativeWindowScriptData[handle] = { url, before, after, l10n, translations }` — while the `nativeWindows[]` entries carry only handle NAMES (`scriptHandle`, `companionScripts` as an ordered handle list, `tabs[].scriptHandle`). The shell joins the two on receipt (`hydrateServerEntries()` in `src/native-windows.ts`, tolerant of the old inline-entry format for cross-version bridge payloads) and injects the data as inline `