What to build
parse() from @vltpkg/dss-parser is meant to reject invalid Dependency Selector Syntax. Currently, it only throws on malformed syntax (unbalanced brackets/parens) — and even then via a generic TypeError: Cannot read properties of undefined, not a validation error.
Semantically invalid selectors (unknown pseudo-classes, nonsense tag words, empty strings, dangling combinators) parse without complaint.
Expected behaviour
parse() should throw a clear, typed validation error when given DSS that could never be a valid selector — unknown pseudo-classes/combinators, empty/whitespace-only input, and dangling combinators — so callers can trust it as a validation gate.
How this surfaced
Found while reviewing the eval harness for the dss-query skill (src/query/skills/dss-query/evals/run.ts) in #1678 for the dss-query agent skill.
The harness grades generated selectors by running them through parse() on the assumption — stated in its header comment and README — that @vltpkg/dss-parser "throws on invalid DSS." Probing the parser directly showed that assumption is false: its "selector validity" check is effectively a no-op for anything short of unbalanced brackets. The harness docs have been softened on the jc/dss-skill branch to describe the real (lenient) behavior; this issue tracks fixing the parser so that check can be strict again.
Reproduction
Run from the repo root (resolves the workspace package):
node --input-type=module -e "
import('@vltpkg/dss-parser').then(m => {
for (const t of [':fake-pseudo', 'not a selector at all', '> >', '', ' ', ':::bogus<<']) {
try { m.parse(t); console.log('NO THROW |', JSON.stringify(t)) }
catch { console.log('throws |', JSON.stringify(t)) }
}
})"
Actual output — every case prints NO THROW:
NO THROW | ":fake-pseudo"
NO THROW | "not a selector at all"
NO THROW | "> >"
NO THROW | ""
NO THROW | " "
NO THROW | ":::bogus<<"
Meanwhile parse(':outdated(') and parse('[name=') throw Cannot read properties of undefined — a crash, not a validation error.
Acceptance criteria
What to build
parse()from@vltpkg/dss-parseris meant to reject invalid Dependency Selector Syntax. Currently, it only throws on malformed syntax (unbalanced brackets/parens) — and even then via a genericTypeError: Cannot read properties of undefined, not a validation error.Semantically invalid selectors (unknown pseudo-classes, nonsense tag words, empty strings, dangling combinators) parse without complaint.
Expected behaviour
parse()should throw a clear, typed validation error when given DSS that could never be a valid selector — unknown pseudo-classes/combinators, empty/whitespace-only input, and dangling combinators — so callers can trust it as a validation gate.How this surfaced
Found while reviewing the eval harness for the
dss-queryskill (src/query/skills/dss-query/evals/run.ts) in #1678 for the dss-query agent skill.The harness grades generated selectors by running them through
parse()on the assumption — stated in its header comment and README — that@vltpkg/dss-parser"throws on invalid DSS." Probing the parser directly showed that assumption is false: its "selector validity" check is effectively a no-op for anything short of unbalanced brackets. The harness docs have been softened on thejc/dss-skillbranch to describe the real (lenient) behavior; this issue tracks fixing the parser so that check can be strict again.Reproduction
Run from the repo root (resolves the workspace package):
Actual output — every case prints
NO THROW:Meanwhile
parse(':outdated(')andparse('[name=')throwCannot read properties of undefined— a crash, not a validation error.Acceptance criteria
parse()throws a typed/descriptive error for unknown pseudo-classes (e.g.:fake-pseudo)parse()throws for empty / whitespace-only input and dangling combinators (> >,:root >):outdated(,[name=) throws a descriptive validation error rather than a genericTypeErrordss-queryeval harness comment/README are updated to note thatparse()now validates semantically