diff --git a/src/parse.spec.ts b/src/parse.spec.ts index 9ebe3738..904bc141 100644 --- a/src/parse.spec.ts +++ b/src/parse.spec.ts @@ -18,3 +18,26 @@ describe("Collected selectors", () => { } }); }); + +const broken = [ + "[", + "(", + "{", + "()", + "<>", + "{}", + ",", + ",a", + "a,", + "[id=012345678901234567890123456789", + "input[name=foo.baz]", + "input[name=foo[baz]]", +]; + +describe("Broken selectors", () => { + for (const selector of broken) { + it(`should not parse — ${selector}`, () => { + expect(() => parse(selector)).toThrow(Error); + }); + } +}); diff --git a/src/parse.ts b/src/parse.ts index 1f98cf1c..2b1ad3b6 100644 --- a/src/parse.ts +++ b/src/parse.ts @@ -211,6 +211,12 @@ function parseSelector( return (slashCount & 1) === 1; } + function ensureNotTraversal() { + if (tokens.length > 0 && isTraversal(tokens[tokens.length - 1])) { + throw new Error("Did not expect successive traversals."); + } + } + stripWhitespace(0); while (selector !== "") { @@ -220,6 +226,7 @@ function parseSelector( sawWS = true; stripWhitespace(1); } else if (firstChar in Traversals) { + ensureNotTraversal(); tokens.push({ type: Traversals[firstChar] }); sawWS = false; @@ -235,6 +242,7 @@ function parseSelector( } else { if (sawWS) { if (tokens.length > 0) { + ensureNotTraversal(); tokens.push({ type: "descendant" }); } sawWS = false;