Fix compiler/core/runtime/reactivity/router/sfc bugs found via systematic audit - #8
Merged
Merged
Conversation
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.
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.
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.