Repository navigation
0.7.2: reused-component hint and source-map fallback, verified on real builds - #30
Merged
Merged
Conversation
When the picked element belongs to a component rendered more than once,
the comment box says "<Card> appears 3 times on this page" and offers
"Just this one" / "Everywhere (the component)" (nothing chosen by
default). The note carries element.reuse = {component, count, estimate,
scope?}; the agent's markdown gets a "Reused:" line, and when no scope
was chosen it is told to ask with reply_annotation before editing the
shared component. The MCP instructions say the same.
Detection (inspector.js, MAIN world, one new function + one call):
React counts fibers of the nearest component's type in the committed
tree from the HostRoot; Vue 3 walks the app root's vnode/instance tree;
plain HTML estimates from tag + classes + parent tag/classes. Capped at
500 matches / 50k nodes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When a minified build has stripped React's _debugSource and Vue's __file, inspector.js hands the nearest component function's own source text and the page's script URLs to the worker, which finds the script that holds it, follows its sourceMappingURL (or SourceMap header; data: and indexed maps too), decodes the VLQ mappings and puts the original file:line and component name into the source hint with method "sourcemap". Same origin (or loopback from a loopback page) only, redirects refused, no cookies, 8 MB per file, 1.5 s total; any failure leaves no hint. No new permission or dependency. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # CHANGELOG.md # extension/content.js
Verified against Vite + React 18/19, Next 15, webpack 5 and Vite + Vue 3.5 production builds; four things only showed up there: - React: the reuse hint said <Vf>. The map's original name now also renames element.reuse, and the popover repaints its meta line and reuse text once the lookup answers. - Vue 3 production sets no __vueParentComponent: the owner is found through the mount container's __vue_app__ vnode tree (vueOwner), used by the framework hint, the reuse count and the map probe. - Vue's generated setup() has no mapping segment of its own, so the segment before it (another module) was taken; the first segment inside the function's head is used instead. - Arrow components carry their name on the `const` binding before the function: look back up to 40 columns in the same source. Tests: e2e-real.test.mjs against committed Vite production bundles of React 18 and Vue 3.5 (test/site/real, rebuilt by test/fixtures/real/build.sh), and unit tests for the segment fallback and the look-back name on those maps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t; Windows-safe test server captureRect and buildAnnotation now run together: the crop is still measured at the moment of Send, but a source-map lookup can no longer hold the note back, so navigating right after Send keeps it (Bug 6 failed on macOS CI). The lookup budget is 4 s: 1.5 s was too tight on a slow runner. The e2e-real test server checked the trailing slash after path.normalize, which uses \\ on Windows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 21, 2026
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.
Both 0.7.2 features in one branch: #28 (reused-component hint) and #29 (source-map fallback) merged together. On top of that, four fixes for things that only broke on real production builds.
What it does
element.reuse, and the agent's markdown gets a "Reused:" line._debugSourceor__file. The clicked component's own code is found in the page's scripts and followed through its source map back to the originalfile:lineand component name (method: "sourcemap").Real-app check (headless Chromium + the extension from this branch, bridge + MCP)
Picks per app:
.card-title(3rd) with Everywhere,.site-title,.price(2nd). "popover" is the meta line and reuse text after the lookup. "note" is the stored annotation. "md" is the agent's markdown.Price)<ProductCard> appears 6 times;element.reuseProductCard×6, scope component; mdReused: <ProductCard> is rendered 6 timessrc/components/ProductCard.jsx:3,Header.jsx:1, method sourcemap<Price> appears 6 times,src/components/Price.jsx:1, name Price<ProductCard>×6, same note and md<ProductCard>×5components/ProductCard.jsx:4,components/Header.jsx:2, sourcemap<ProductCard>×6,<Price>×6<PriceCard> appears 4 times;element.reusePriceCard×4, estimate false; md Reused linesrc/components/PriceCard.vue:3,SiteHeader.vue:6, framework vue, sourcemap<ProductCard>×6,<Price>×6_debugSource, no map lookup<ProductCard>×6_debugStack(components/ProductCard.jsx:20)<PriceCard>×4__fileThe only console errors were favicon 404s.
The four fixes
<Vf>) in the popover, inelement.reuse.componentand in the markdown.applyMapSourcenow also renameselement.reuse.componentwhen it matches the minified name.paintMetawaits for the lookup, then repaints the meta line and the reuse text with the original name, as long as the same element is still picked.el.__vueParentComponentandapp._instanceexist only in dev builds. A newvueOwner(el)uses__vueParentComponentwhen it is there. Otherwise it finds the nearest container with__vue_app__, walkscontainer._vnode.component's vnode tree (bounded at 50k), maps each element to the instance that owns it, and returns the nearest owner.vueHint,reuseHintandmapProbeall use it.setup(e){, and Vue's generated setup wrapper has no mapping segment. Greatest-lower-bound then picked the previous module's segment.originalPositionnow uses the first segment inside the snippet (within 120 columns) when the found one starts before it, or when none is found.names[]puts "Price" on theconst Af=binding just before the function text, and the name search only looked forward. It now also looks back up to 40 columns in the same source file, taking only the nearest named segment.Tests
test/e2e-real.test.mjsruns against real Vite production bundles that are committed intest/site/real/{react,vue}(React 18.3.1, Vue 3.5.44). They are rebuilt bytest/fixtures/real/build.sh; CI does not build them.<ProductCard> appears 3 timesin the popover after the lookup, and the note and markdown say the same. Source issrc/components/ProductCard.jsx, method sourcemap.Priceresolves tosrc/components/Price.jsxunder its real name.<script setup>SFC rendered 3× shows<PriceCard> appears 3 times(estimate false), with sourcesrc/components/PriceCard.vue.test/ui-sourcemap.test.mjs: unit tests on those same real maps. The Vue setup() segment fallback (the test also asserts that the segment before it belongs to another module), and the arrow look-back name. A function declaration still takes the name afterfunction.web-ext lintgives 0 errors and 1 warning, the existing Firefox-for-Android min-version warning.🤖 Generated with Claude Code