fix: harden frontend overlay's cssUrl injection and preview effect (PL-029/030/031) - #138
Conversation
…names SLASHED's SL-016 (codec.ts's `fa` → `generateCSS`) and SL-022 (lucide-svelte → @lucide/svelte) landed in main via #474. AppOverlay.svelte is plugin-specific and not vendored, so it kept referencing the old names and broke `vite build` as soon as CI's prebuild sync pulled the renamed exports from slashed@main — failing on every open plugin PR, not just the one that triggered it. Swaps the import/call site to generateCSS and updates package.json/ package-lock.json to depend on @lucide/svelte instead of the deprecated lucide-svelte package.
npm run check (svelte-check) had no equivalent of dev/build's predev/prebuild sync hook, so it type-checked whatever was already on disk. On a fresh checkout with the committed vendored src/ still predating the lucide-svelte rename, that meant a stale module-resolution error instead of an accurate check against the current framework source.
…review effect PL-029/030: window.slashedApp is a plain global any script on the page can clobber before plugin-main.ts runs. Add a same-origin check before using cssUrl as a stylesheet href, and replace the (window as any) cast with a typed local accessor (mirroring persistence.ts's own window.slashedApp read) instead of widening to any. PL-031: AppOverlay.svelte's live-preview effect (injectLivePreview + registerPreviewDoc) re-ran on every override change with no coalescing, unlike PreviewPanel.svelte's SL-020 fix. A fast-changing control (dragging a slider) could re-run it many times per frame even though the underlying <style> rewrite only needs to happen once per paint. Wrapped it in the same rAF-coalescing pattern.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
PR Summary by QodoHarden frontend overlay cssUrl injection and debounce live preview
AI Description
Diagram
High-Level Assessment
Files changed (3)
|
Code Review by Qodo
Context used✅ Compliance rules (platform):
1 rule 1.
|
…iew effect Svelte 5's \$effect only tracks reactive reads that happen during its own synchronous execution. The rAF-coalescing added for PL-031 read overrides only inside the (later-firing) requestAnimationFrame callback, so the effect would never re-run after the first paint -- the live preview would silently stop reacting to override changes. PreviewPanel.svelte's SL-020 fix (the pattern this was meant to mirror) already captures its reactive dependencies synchronously before entering the rAF callback for exactly this reason -- this file just missed it.
5fe0c8a
into
claude/pr-469-audit-rebase-ggp0e4
Summary
Third PR from SLASHED-Plugins' technical-debt audit remediation (Wave 0, plugin-specific frontend hardening —
AppOverlay.svelte/plugin-main.tsonly, neither vendored).cssUrlinjection):plugin-main.tssetlink.href = cssUrlfromwindow.slashedApp?.cssUrlwith no validation.cssUrlis normally trustworthy — server-generated viaesc_url_raw()over the plugin's own asset path (class-frontend-configurator.php) — butwindow.slashedAppis a plain global any other script on the page (a theme, another plugin) can clobber before this module runs. Added a same-origin check (new URL(url, location.href).origin === location.origin) before using it as a stylesheethref; on failure it falls through to the existing unstyled-mount fallback rather than blocking.window.slashedAppaccess): replaced the(window as any).slashedApp?.cssUrl as string | undefinedcast with a typed local accessor. Initially tried adding a plugin-owned ambient.d.tsaugmenting the globalWindowinterface, but that conflicts with the vendoredvite-env.d.ts's ownWindow.slashedAppdeclaration (TS interface-merging two incompatible shapes for the same global property brokesvelte-check). Instead mirrored the exact local-intersection-type pattern the vendoredpersistence.tsalready uses for its ownwindow.slashedAppread (window as Window & { slashedApp?: T }) — no global declaration, no merge conflict.AppOverlay.svelte's live-preview effect): theinjectLivePreview/registerPreviewDoceffect re-ran on every override change with no coalescing, unlike the framework's ownPreviewPanel.svelte(SL-020, already fixed upstream). A fast-changing control (dragging a slider) could re-run it many times per animation frame even though the<style>rewrite + derived-token recompute only need to happen once per paint. Wrapped it in the samerequestAnimationFrame+cancelAnimationFramecleanup pattern as SL-020.Verification
npm run check(svelte-check): 0 new errors (the one remaining error,plugin-main.ts's.tsimport extension, is pre-existing and unrelated).npm run build: succeeds, 216 modules.npm test: 67/67 passing.isSameOrigin()'s logic (relative paths, same-origin absolute URLs, cross-origin, protocol-relative, andjavascript:URLs) via a standalone script — correctly allows same-origin/relative, rejects everything else.Type
Checklist
npm testpassesnpm run lintpassesnpm run verifypassesCHANGELOG.mdupdated — not user-facing (internal hardening, no behavior change for the trusted/normal path)src//assets/predate the framework audit sync (separate PR-SYNC job), and CI always rebuilds from a fresh sync regardless of what's committed hereNotes
Depends on #135 (codec/lucide rename hotfix) being present on this branch's base to build — already merged into this branch directly since #135 hadn't landed on the integration branch yet.
Generated by Claude Code