fix(import): make emitted ui.js self-contained (relative asset paths)#6413
Merged
Conversation
The import CLI stamped decode-time ABSOLUTE paths into the generated JS (setImageSource/setKnobSpriteStrip/registerFont): for `--from fig` these point into the per-run $TMPDIR/pulp-fig-* scratch dir, which is deleted when the run exits, so re-rendering the export later silently lost every image; `--validate` only worked because it renders before cleanup. Other lanes kept paths into whatever directory the envelope happened to be decoded in — broken as soon as it moved. Fix, general to every JS-emitting lane: - `localize_ir_assets` (sprite_skins.cpp) runs after asset resolution and before codegen: it copies each referenced image/font into `assets/` next to the `--output` file and rewrites the IR references to output-relative `assets/<file>` paths. Skipped for --dry-run and baked emits. - `WidgetBridge::set_script_base_dir` resolves those relative paths against the script's own directory at the path-taking bridge APIs, regardless of process CWD. Unset base keeps the historical CWD behavior, and unlike set_asset_roots it never restricts loadAsset. The `--validate` render, pulp-screenshot, and pulp-design-tool set it from the script location. - `make_scratch_dir` now sweeps stale (>24h) `pulp-<tag>-*` siblings: runs killed mid-decode never reach their cleanup destructor, and ~160 leaked scratch dirs had accumulated in $TMPDIR. The age floor leaves concurrent live imports untouched. Tests: self-containment pin (relative paths emitted, assets copied, export intact after the decode dir is deleted), scratch-cleanup + stale-sweep pin, script-base-dir resolution unit sections, and the ZIP-sidecar test updated to the new relative contract. Hotspot-Grow: core/view/include/pulp/view/widget_bridge.hpp reason="script-base-dir resolution API needed for self-contained import artifacts" Hotspot-Grow: tools/import-design/pulp_import_design.cpp reason="wire asset localization + validate-render base dir (+10 LOC)" Compat-Update: skip prefix=canvas2d reason="host-side script-base-dir path resolution API; no web-compat surface change" Compat-Update: skip prefix=css reason="host-side script-base-dir path resolution API; no web-compat surface change" Compat-Update: skip prefix=html reason="host-side script-base-dir path resolution API; no web-compat surface change" Compat-Update: skip prefix=imports reason="host-side script-base-dir path resolution API; no web-compat surface change" Compat-Update: skip prefix=react reason="host-side script-base-dir path resolution API; no web-compat surface change" Compat-Update: skip prefix=rn reason="host-side script-base-dir path resolution API; no web-compat surface change" Compat-Update: skip prefix=yoga reason="host-side script-base-dir path resolution API; no web-compat surface change" Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014e8kbMn8Sf4mF8ozsy1Jot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Item #3 of the Figma-import hardening plan (
planning/2026-07-20-figma-import-hardening-plan.md).Exported
ui.jsreferenced decode-time temp asset paths ($TMPDIR/pulp-fig-*/assets/…) that are deleted at run end — so re-rendering the export silently lost every image/font.--validateonly passed because it renders before cleanup.Fix (general — every JS-emitting lane)
localize_ir_assetscopies referenced images+fonts into anassets/dir next to--outputand rewrites the IR to output-relative paths (collision-suffixed; copy failure degrades to a warning, never fails the import).WidgetBridge::set_script_base_dir/resolve_script_relativeresolves relative fs paths at the asset-taking APIs against the script's dir (unset = historical CWD behavior; deliberately not the sandboxingset_asset_roots). Wired into--validate,pulp-screenshot,pulp-design-tool.make_scratch_dirnow sweeps stalepulp-*scratch dirs >24h (drained a 161-dir backlog from killed runs; live imports untouched).Verification
setImageSource→ relativeassets/…(dedup'd texture copied alongside), zero functional/var/foldersrefs (the one left is a// Source:provenance comment). Re-rendered standalone from/→ content renders (assets resolve via base-dir, not CWD).ctest -R "import|design|asset|codegen|native"617/617;-R "bridge|widget|screenshot|font"408/408. New tests pin the self-contained artifact (survives decode-dir deletion), the scratch-dir sweep, and base-dir resolution.🤖 Generated with Claude Code
🔎 Provenance
claudem5w1~/Code/fig-fixfd0e374f-d5dc-4e2a-bb33-6fa8b66124a0Resume
Jump to this tab
Relaunch (any agent)
Restore URL — https://claude.ai/code/session_014e8kbMn8Sf4mF8ozsy1Jot
stamped 2026-07-20 22:40 UTC