Skip to content

Source hint for production builds, through the page's source maps - #29

Closed
gowtham012 wants to merge 1 commit into
mainfrom
feat/sourcemaps
Closed

gowtham012 wants to merge 1 commit into
mainfrom
feat/sourcemaps

Conversation

@gowtham012

Copy link
Copy Markdown
Owner

When a production build has stripped the framework's debug info (React _debugSource / _debugStack, Vue __file), Pinpoint now maps the clicked element back through the page's source maps to the original component and file.

How it works

  1. inspector.js (MAIN world) answers a new pinpoint:probe event: the nearest component's function (fiber .type / .type.render / .type.type, Vue setup / render), the first 120 chars of its Function.prototype.toString, and the page's script URLs (document.scripts and performance resource entries with initiatorType: "script").
  2. content.js asks for this only when the hint has no file and the framework is React or Vue. It starts when the popover opens, so the lookup is usually done by Send. The crop is now measured before the note is built.
  3. The service worker (extension/sourcemap.js) keeps only allowed URLs, fetches them, finds the snippet (it must appear exactly once) and gets a 0-based line/col. Then it reads the last //# sourceMappingURL= or the SourceMap / X-SourceMap header (data: and relative URLs work), decodes the VLQ mappings, takes the segment at or before that position, and returns {file, line, column, name}. sources[] are cleaned to project-relative paths. Indexed maps work; url sections are skipped.
  4. The note's source gets method: "sourcemap", and the minified name in the component chain is replaced by the original PascalCase names[] entry. The agent markdown says "(found through the page's source map)".

Why the worker: the page's CSP connect-src and any fetch override the page has installed play no part, and the page never sees the requests. The allowed origin comes from sender.url, never from the message. It runs only for local dev pages.

Limits: only same origin, or loopback from a loopback page; a map on a CDN or other host is never requested. Redirects are refused, no cookies are sent, the cap is 8 MB per file, the budget is 1.5 s, and results are cached per URL for 60 s (8 entries). Inline and eval'd scripts are not listed, so they are not found. Code-split chunks work only if the chunk appears in performance entries (lazy chunks loaded with import() do). A function text that appears twice gives no hint. Sources under node_modules give no hint.

No new manifest permission and no new dependency. Firefox's background.scripts gains sourcemap.js.

Tests: ui-sourcemap.test.mjs (10 tests: VLQ, a check against source-map-js on every segment of a real esbuild map, lookup, cleanup, indexed maps, fetch policy, resolve with cache/data:/cross-origin/timeout) and e2e-sourcemap.test.mjs (production bundle → src/components/PriceTag.js:9 via sourcemap; a map on another origin is never requested and gives no hint). Full suite: 227 tests, 226 pass, 0 fail, 1 skipped. Firefox package web-ext lint: 0 errors.

🤖 Generated with Claude Code

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>
@gowtham012

Copy link
Copy Markdown
Owner Author

Included in #30 (merged), together with fixes found by testing on real Vite/React/Next/webpack/Vue production builds.

@gowtham012 gowtham012 closed this Oct 21, 2026
@gowtham012
gowtham012 deleted the feat/sourcemaps branch October 21, 2026 13:36
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