Skip to content

Fix compiler/core/runtime/reactivity/router/sfc bugs found via systematic audit - #8

Merged
aldanedev-create merged 2 commits into
mainfrom
fix/vel-runtime-and-css
Aug 26, 2026
Merged

Fix compiler/core/runtime/reactivity/router/sfc bugs found via systematic audit#8
aldanedev-create merged 2 commits into
mainfrom
fix/vel-runtime-and-css

Conversation

@aldanedev-create

Copy link
Copy Markdown
Owner

Cumulative branch covering a full audit-and-fix pass across the teloce monorepo: CLI, debugger, .vel compiler/runtime, scoped CSS, component composition, custom directives, global state, reactivity, router, and SFC parsing. See individual commit messages for full details on each fix, all verified with real compile-and-run tests against the built packages.

Continued the @teloce/sfc audit, found one more instance of the same
"search anywhere instead of top-level-only" bug class as the previous
commit's methods/computed/props/lifecycle-hook fixes - this time in
parser/index.ts's extractComponentName.

extractComponentName correctly brace-balanced its way to the full
export-default object's content, but then searched that entire text
with a plain `objContent.match(/name\s*:\s*(['"])([^'"]+)\1/)` for the
component's name - matching the *first* occurrence of `name:` anywhere,
including nested inside another property's value, not just the actual
top-level `name` field.

Confirmed with a realistic case: `data() { return { user: { name:
'Alice' } }; }, name: 'RealComponentName'` (data() listed before name,
an ordering some style guides actually recommend) extracted "Alice" as
the component's name instead of "RealComponentName". This matters more
than a wrong label - the extracted name also becomes the exported
const's actual variable name in the generated code
(`export const ${name} = defineComponent(...)`), so a wrong value
pulled from arbitrary nested string data could contain characters
invalid in a JS identifier (spaces, punctuation) and produce outright
broken, non-compiling output.

Fixed with the same depth-and-string/comment-aware top-level-key
scanning technique as the previous commit (duplicated locally rather
than imported, to keep this file's SFC-block-splitting concern
independent from script/index.ts's property-extraction internals).
Verified: the nested-name case now correctly extracts
"RealComponentName", the original name-before-data ordering still works
unchanged, and a component with no top-level name at all still falls
back to the default name correctly.

Verified: full regression sweep across everything from this session and
previous ones still passes, plus a full "pnpm -r build" across the whole
workspace with zero errors.
…ute landing on the wrong selector segment

Continued the @teloce/sfc audit into style/index.ts's CSS scoping logic
(the most careful, well-written part of the parser found so far -
proper string/comment-aware tokenizing, correct @media/@supports/
@Keyframes handling) - but found two real bugs even there, both
confirmed with real compile tests.

<style scoped> attribute silently discarded (packages/sfc/src/
parser/index.ts, compile.ts):
- parseBlock() only ever read a `lang="..."` attribute off a block's
  opening tag - it never checked for the `scoped` boolean attribute at
  all, so `<style scoped>` and plain `<style>` were parsed completely
  identically. Whether a component's CSS actually got scoped was
  controlled entirely by an external, global `scoped` compile option
  (defaulting to false at the compile() level), with zero way for an
  individual .vel file to opt in or out for itself - exactly the kind of
  per-component control that attribute syntax is supposed to provide.
  Fixed: parseBlock now detects the `scoped` attribute, SFCResult
  exposes it as `styleScoped`, and compile() uses it as the authoritative
  source whenever a <style> block exists (options.scoped remains as a
  fallback only for callers with no real <style> tag to read from).
  Verified: `<style scoped>` and plain `<style>` in different files now
  correctly produce scoped and unscoped CSS respectively, with no
  external option needed.

Scope attribute applied to the wrong selector segment (packages/sfc/
src/style/index.ts):
- The pseudo-class-aware scoping logic ran on the *entire* selector
  string as one unit, finding the first root-level colon anywhere in
  it. That's correct for a single compound selector, but for a
  combinator chain with a pseudo-class on an *earlier* segment - e.g.
  `.parent:hover > .child:focus` - it incorrectly attached the scope
  attribute to `.parent` (the wrong target - an earlier segment in a
  combinator chain should never be scoped, matching how this same
  scoper already correctly handles plain multi-segment selectors like
  `.parent .child` -> `.parent .child[attr]`, scoping only the last
  segment) while leaving `.child` - the actual last/target segment -
  completely unscoped. Confirmed via direct compilation: the emitted
  CSS had the attribute in the wrong place entirely, with the segment
  that should have been scoped left bare. Fixed by splitting each
  selector on its last top-level combinator first (correctly skipping
  combinator-like characters inside parentheses, e.g. `:not(.a > .b)`)
  and only running the existing pseudo-class-aware logic on that final
  segment, leaving everything before it untouched.

Verified with a comprehensive selector sweep: plain classes, ID
selectors, descendant/child/sibling/general-sibling combinators, a
simple pseudo-class, the previously-broken pseudo-class-on-an-earlier-
segment case, comma-separated selector lists mixing plain and
pseudo-class forms, :not() with a combinator inside it, and multi-level
descendant chains ending in a pseudo-class - all now produce correctly
and consistently scoped CSS. Also re-verified @media/@Keyframes
handling (unaffected, still correct) and the original scoped-CSS
injection scenario from an earlier session's fix still works end to end.

Verified: full regression sweep across everything from this session and
previous ones still passes, plus a full "pnpm -r build" across the whole
workspace with zero errors.
@aldanedev-create
aldanedev-create merged commit 1e93a69 into main Aug 26, 2026
1 check passed
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