Skip to content

feat(svelte): add compiler-backed Svelte 5 semantic extraction#2013

Open
mafifi wants to merge 4 commits into
Graphify-Labs:v8from
mafifi:feature/svelte-5-semantic-support
Open

feat(svelte): add compiler-backed Svelte 5 semantic extraction#2013
mafifi wants to merge 4 commits into
Graphify-Labs:v8from
mafifi:feature/svelte-5-semantic-support

Conversation

@mafifi

@mafifi mafifi commented Jul 18, 2026

Copy link
Copy Markdown

Summary

Graphify currently recovers some Svelte imports, but regex and whole-file JavaScript scanning cannot reliably preserve Svelte author semantics. In particular, a component importing a class-based .svelte.ts ViewModel can produce a phantom .svelte target, and template/script relationships lose binding identity and trustworthy source locations.

This change adds compiler-backed Svelte 5 semantic extraction:

  • pins and reproducibly bundles svelte/compiler and parses parse(source, { modern: true }) author ASTs;
  • walks ast.fragment generically for ESTree expressions, while handling special Svelte node semantics through a typed exhaustive schema policy and golden syntax corpus;
  • uses svelte2tsx plus TypeScript only for semantic binding identity and maps all facts to original author offsets; generated TSX is never graphed;
  • owns parsed facts in one extraction-scoped batch context, with a bounded success/degradation LRU only for reuse across later runs;
  • treats module and instance scripts as independent lexical programs and preserves compiler-owned import identities, aliases, byte ranges, and script context;
  • joins through the canonical Python module resolver, including barrels, aliases, bare paths, .svelte.ts/.svelte.js, real-.svelte precedence, and symlink-normalized identities;
  • emits traceable component render, prop-flow, construction, member-read, and method-call relationships using existing relation vocabulary where possible, with exact EXTRACTED/INFERRED provenance;
  • recognizes only compiler-valid rune forms for state, derived values, and effects, and records deterministic syntactic dependencies without claiming runtime behavior;
  • degrades explicitly when Node or compiler support is unavailable instead of promoting regex guesses to extracted facts.

The bridge requires Node >=18. Its intentionally bundled compiler/semantic toolchain is 12,441,699 bytes raw (about 2,115,201 bytes gzip); a non-brittle growth guard prevents accidental explosive expansion. The compiler schema gate, deterministic bundle build, lockfile, and third-party notices make upgrades reviewable and reproducible.

Verification

  • Full Python suite: 3457 passed, 33 skipped
  • Focused Svelte/resolver/Vue/Astro/wheel lane: 330 passed
  • Bridge npm test: typecheck and schema corpus pass for Svelte 5.56.6 (38 template + 2 structural AST variants)
  • Ruff: clean
  • git diff --check: clean
  • Two bridge rebuilds produced identical hashes:
    • bundle: 95d5da5146b2a3cd14035d3f28450e4d027493ebf53f9da00d3e8b1d2349df2f
    • notices: 9bee87a228b5fb3f03b42fc1edb4278513c318ed3edf206dfd0c3ca326ae1dee

Coverage is synthetic and includes adversarial text/comment/tag lookalikes, mixed script languages, module/instance scope collisions, shadowing and aliases, all expression containers including dynamic imports, component rendering and prop flow, ViewModel construction/member access/calls, exact rune forms, canonical/symlink resolution, pruning, negative and bounded caching, incremental refresh, UTF-8 offsets, packaging, and degradation.

This builds on Christian Winther's import-recovery work in #714, which addressed #713, and composes with the TypeScript bare-path and .svelte.ts/.svelte.js resolver work merged in #717. Those changes are prior foundations; this PR extends the architecture beyond their original scope.

mafifi added 4 commits July 18, 2026 22:28
Pin and bundle the Svelte compiler, svelte2tsx, and TypeScript semantic toolchain with an exhaustive schema policy, golden author-syntax corpus, deterministic notices, and Node 18 runtime contract.
Parse each compiler-owned module and instance script as an independent lexical program, retain extraction-scoped author facts, and join binding identities through the canonical JS resolver.

This builds on Christian Winther's Svelte import-recovery work in upstream PR Graphify-Labs#714 and composes with the resolver foundations merged in Graphify-Labs#717.
Add synthetic adversarial fixtures for script scopes, binding identity, component and ViewModel relations, rune syntax, resolver behavior, cache ownership, incremental refresh, wheel contents, and bundle growth.
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